Haha, this one is good. However after longer time working with Elixir, for me there is not such need to want OOP back
@OvermindDL1 wow
I do think itâs valid to think about interoperability when it comes to JavaScript classes. Since JavaScript may or may not be heading in a class heavy direction. My current recommendation is to define them in JavaScript and use them in Elixirscript if you have to. As more people start using Elixirscript and thinking about it more, there may be a more elegant solution.
What I would LOVE to do is expose the JavaScript AST in Elixirscript, let anyone with the knowledge do whatever they want with it, have the JS AST returned to Elixirscript and go on from there. I donât know where to begin with that one, but it would be nice.
Just published version 0.27.0 of elixirscript. One major change is that super
and defoverridable
are now implemented. The other is that JavaScript functions, properties, and modules can now be accessed from the JS
module, examples: JS.alert("hi")
, JS.console.log("hi")
, JS.Date.now()
For the rest of the changes, please check the changelog
@bryanjos: Well done!
One small tip: please include all modules in your namespace module like:
defmodule ElixirScript.JS do
# ...
end
because you are using bad practice.
Imagine that I want to add another dependency to my project with for example JavaScript analyser/parser or similar library.
When two libraries declares modules with same names then itâs easy to get conflict sooner or later.
We can alias
your modules, but donât know how hard will be to resolve module conflicts.
Anyway, good work and thanks to implement my comments!
No new release just yet, but thought Iâd send an update.
Thanks to the changes in OTP 20 and Elixir 1.5, ElixirScript was rewritten and can now support almost all Elixir features besides receive
. More information is in this blog post.
Another addition is a change in JavaScript interoperability with an FFI module. More information on that can be found here
Next Iâve update the Todo Example to work with ElixirScript in master. I have taken the react parts in made it into a library that it uses. Showing how an ElixirScript library could look. Basically a normal mix project with javascript files in the priv folder if neeeded.
Most of the work now is implementing whatever Erlang calls Elixir makes in JavaScript. Thatâs where contributions to the project are definitely the most helpful. The other is in fixing bugs that appear along the way.
For a release, hoping to have something before ElixirConf.
P.S: receive
Want to support this eventually. I would like to be able to implement a process system in JavaScript using async/await and use that in ElixirScript, but my brain canât quite grasp how to do so. Any help there would be appreciated
Edit: Or using the current implementation that uses generators is a possibility, but async functions seem to play better with normal javascript functions.
What about using webworkers? They communicate by messaging too, soâŠ
WebWorkers are limited (for security), so you canât:
- Access DOM, because itâs not
thread safe
document
objectparent
objectwindow
object- send message with function definition, because messages using for communication are converted to JSON format
So I think that async/await would be better for full API support and WebSockets could be optionally implemented also.
@bryanjos: This is sample code from Polish tutorial (I translated messages only):
var worker = new Worker('background.js');
// register `message` event listener - handle message from worker thread
worker.addEventListener('message', function(e) {
alert('received answer: ' + e.data);
}, false);
// send start message
worker.postMessage('start');
// send stop message
worker.postMessage('stop');
/* ---------------- source code of background.js ---------------- */
// register 'message' event listener - handle message from parent thread
this.addEventListener('message', function(e) {
switch(e.data) {
case 'start':
this.postMessage('thread started!');
break;
case 'stop':
this.postMessage('thread stopped!');
this.close(); // stop this worker
break;
default:
this.postMessage('unknown command!');
}
}, false);
in case you decide to use WebWorkers API for this purpose.
Webworkers are a bit too heavyweight to work since they are pretty much threads. But they may work. There was another reason that I canât remember why I stayed away from them that I canât remember.
Edit: Now I remember. What @Eiji said about not having access to everything
Edit again: Also receive
in Elixir is synchronous, but itâs not in web workers unless you wrap it in a promise and then use async/await anyways.
Precisely!
The DOM and everything related to it should be accessed by a single âthreadâ, messages should be posted to it to alter it in some way, just like you message GenServerâs now.
You could always term_to_binary and vice-versa back or use some other encoding format to marshall data across.
Well you could break up a âprocessâ to carry around and use its own stack, then you have greenthreads, and could keep it on the main thing then.
Honestly Iâd say donât both making receive or threads of any form, javascript is way too different to be able to wrap it in OTP well unless you used emscripten to recompile the BEAM itself to run on the client itself (which you could do).
Yeah the plan right now is just to not support receive
until there is a clearer solution or more resources. But I do know it is possible
ElixirScript 0.30.0 is now published in Hex. This release has many changes from previous versions. For more information, check out this blog post, the changelog, and the docs.
From what I understand, Elixirscript compiles Elixir to erlang and then converts erlang to Javascript, right?
This means that I canât convert isolated elixir expressions into Javascript expressions based on the AST of Elixir and not the compiled output. I was thinking of something like f(x, 1, %{a: 1, b: 2})
bring converted into f(x, 1, {a: 1, b: 3})
.
Is there anything in Elixirscript that can help me do this, or my best bet is to write a custom solution myself?
I donât think elixirscript runs on erlang bytecode. From the readme:
This is done by taking the Elixir AST and converting it into JavaScript AST and then to JavaScript code. This is done using the Elixir-ESTree library.
I havenât looked at the source, but from the blog:
Calls to Erlang functions that the Elixir standard library make have to be reimplemented in JavaScript. There are many that are implemented, but there are more that need to be. This effects the availability of some Elixir standard library calls. A major contribution to ElixirScript would be to help with an implementation of an Erlang function that is blocking the use of an Elixir function you want to use!
Any usage examples / use cases mates?
I wanted to offer some feedback:
I am glad you have been working on compiling Elixir to JS. But what Iâd really like to see is a ReactJS-like experience on the frontend. What I mean by that is:
-
keep the modules structure of Elixir, where anything in the project can be accessed without needing to know the specific file path or explicitly export anything
-
keep the ability for Elixir syntax to be transpiled to JavaScript
- otherwise, remove the quirks and follow the structure of React
Iâll elaborate on the third point.
My main beef with JavaScript is the syntax includes meaningless, âboilerplateâ characters. Conversely, I really like JSX. While itâs already too late and doesnât mean much coming from a stranger, I think you went in the wrong direction with a DSL different from JSX.
I wish I could write a file like this:
# App.ex
defmodule ProjectName.App do
use React # EX
import ReactNativeWeb
alias ProjectName.ErrorBoundary
def mount,
do: IO.inspect "Mounted!"
def render(props, state) do
<ErrorBoundary>
<Text elixir={
if Platform.OS == "web", do: "web", else: "screen"
}/>
</ErrorBoundary>
end
end
This would render the text web
on your computer or screen
on your phone.
In the JSX article, there is a quote:
Angular, Ember and Knockout put âJSâ in your HTML.
React puts âHTMLâ in your JS.
The analogy here is:
ElixirScript puts âJSâ in your Elixir.
What I have proposed puts âElixirâ in your JSX.
I.e. Yes, Elixir is more powerful than JSâthatâs why weâre replacing it. But, I hope youâd agree that JSX is a better DSL for the frontend.
From an implementation standpoint, this may mean creating a JSX DSL for Elixir (like Phoenixâs Ecto is for SQL queries).
I.e. Keep Reactâs design patterns and JSX. Replace JavaScriptâs syntax with Elixirâs.
Actually, you donât even need to handroll the DSL. You can just have a special render
macro which accepts a do:
block with JSX as its last argument.
I know this isnât exactly what you are envisioning embedded directly into Elixir but have you looked at ReasonML with ReasonReact?
Thatâs what I am happily using to get JSX with elixir style âmoduleâ/component structure you are talking about (no explicit importing/exporting) and great type inference.
ElixirScript works at a level where if you can do what you defined in standard Elixir, itâs work in ElixirScript. Iâd be interested if anyone did what you prescribed. There was an ElixirScript issue open for almost a year about JSX but nothing really came about from it.
Googling, JSX has not yet come to Elixir⊠Anyone know off the top of oneâs head about other languages that have implemented it?
I found this article. In a nutshell, JSX syntax is merely syntactic sugar for an AST of React.createElement
calls.
If youâve seen the library Shorthand
, it allows one to create maps with JS-like behavior: m(item) => %{item: item}
. For ElixirScript, you could simply have a function jsx(type, props, children)
that evaluates to the JS equivalent.