clojerl / clojerl Goto Github PK
View Code? Open in Web Editor NEWClojure for the Erlang VM (unofficial)
Home Page: http://try.clojerl.online/
License: Eclipse Public License 1.0
Clojure for the Erlang VM (unofficial)
Home Page: http://try.clojerl.online/
License: Eclipse Public License 1.0
The following reader dispatches are not implemented:
`sym
)%
, %nand
%&`)#()
)#=1
)#?(:clj 1 :cljs 2)
)Possible when the repo goes public.
This is more complex than just allowing arbitrary expressions as binding forms.
A possible approach would be translating Clojure's destructuring syntax to Erlang's valid patterns. We could cover the most basic patterns (i.e. lists and maps) this way and extend the destructuring syntax for all the Erlang pattern syntax not covered.
Another option would be to have both separately. Destructuring would be used in the default Clojure macros (i.e. defn
, let
, loop
) and new equivalent macros would allow the usage of Erlang patterns when binding values (i.e. defn.e
, let.e
, loop.e
).
If the var
contains a function, when the emitted erl_fun
function value is applied or the emitted application expression is executed, it might result in an undefined function
error. Or (even more confusing for the user) if the var defined after is a function with a variadic arity, then the application emitted has as many arguments as the ones provided in the original form, which might not match the ones the existing function should receive for its variadic application.
If the var
contains a value then it will most likely result in an undefined function
.
The current approach forces the generation of a module for each implementation of any given protocol. The advantage of this is that it allows extending a data type without having to modify its module.
It could be changed so that the code for the protocol mechanism looks for the implementation in the data type module and then if it's not there then look for an implementation module. The problem with this approach is that for two different protocols with functions that share their names, there could only be a single implementation, unless the function name in the module has the protocol's name as a prefix. The prefix should actually need to be the protocol's fully qualified name to avoid collision between two protocols with the same name.
For example the following protocol generates a module clojerl.Counted
with a callback count/0
:
(ns clojerl)
(defprotocol Counted
(count []))
If we want to implement the protocol for the type List
, the current approach would mean generating a module clojerl.List.clojerl.Counted
that implements the behavior. An alternative approach is to consolidate all implementations in the same module, either the protocol's or the type's module. This would mean loading the module's code and inserting the implementation function, which has challenges of its own.
And fold over forms maintaining the Env. This is necessary to correctly keep track of the current namespace based on the analyzed/emitted/evaled forms so far.
The reader should provide a way to read one form and return the remaining unconsumed input.
When the repo goes public.
An Erlang atom is a lot closer to a Clojure keyword than to a symbol since their usage is a lot more common in Erlang as keys to maps and values used to tag data. The trade-off is that it won’t be possible for keywords to have any metadata associated to them. Additionally the Erlang atom undefined
will be mapped to Clojure’s nil
and vice versa.
Clojure symbols will still be a boxed type so that they can provide support for metadata.
Erlang atoms are a viable option for keywords and/or symbols.
The advantage of using atoms is that they are maintained in the atoms table so each time a symbol is created it would be equivalent to Java’s String.intern() (although it seems Clojure JVM is not interning the string for symbols and Keywords anymore).
The disadvantage is that a lot of name munging is involved when manipulating symbols and keyword. If atoms are used, a bunch of conversions between atom to binary and or binary to atom will be needed. For example, if the keyword clojure.core/str
is represented by an atom, extracting the namespace and/or name from this keyword would involve converting to binary and splitting by the first “/” character found.
Either emit the compile-time information of the var or get the run-time information for it.
Read http://www.cs.cmu.edu/~rwh/theses/okasaki.pdf once and for all!
The analyzer is currently returning an erl_fun
node for all symbols that can't be resolved to locals or existing vars so it doesn't really make sense to have a specific reader that returns an Erlang fun
.
The following compiles but doesn't work:
(def comp
(fn* [& fs]
(fn* [& xs]
(clojure.core/apply (clojure.core/first fs) xs))))
Compare the Clojerl
implementation to tools.analyzer
implementation, there might be some things missing.
The function would cause the required module to be compiled and loaded in the runtime. If the compile-time Env
is not modified then issue #53 should be implemented with this one so that a namespace can require another namespace and just use the vars defined in it.
Since all the module is now being compiled at once, the first time it is compiled all vars that are macros can't be executed because they don't exist yet. A possible solution would be to partition the forms in a module every time a macro is found.
The idea would be to test their expected behavior implemented through the protocols they implement.
Value Types:
clojerl.Boolean
clojerl.String
clojerl.Integer
clojerl.Float
clojerl.Nil
Named Types:
clojerl.Symbol
clojerl.Keyword
clojerl.Var
Collection Types:
clojerl.Map
clojerl.List
clojerl.Set
Erlang Types:
clojerl.erlang.List
clojerl.erlang.Map
clojerl.erlang.Tuple
clojerl.erlang.Fn
deref
ing the value of a private var should only work in the module the var is defined, but this won't work since the whole process of deref
ing involves other modules already (i.e. clojerl.Var
).Compiler tests are failing because the output dir is hard-coded, by fixing this issue we could provide the output dir as an option.
Since we have no threads in Erlang the value would actually be associated to a process. This sounds like the process dictionary is a good fit for dynamic values to live in. We can reuse the clj_scope
data structure to handle nested bindings.
One of the main issues is that Clojure functions can have a variadic number of arguments. This presents the challenge of detecting functions whose last argument is variadic while keeping interop as simple as possible.
In the function call (f 1 2 3)
, the symbol f
could resolve to a var
, local binding
or nothing. If it's a var
and its value is a clojerl function then it should be invoked depending on whether it's the variadic arity or not.
With the current metadata implementation, the same symbol with different metadata won't be mapped to that key 😞.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.