OvermindDL1

OvermindDL1

MLElixir - attempting an ML-traditional syntax entirely within the Elixir AST

Been making an MLElixir thing (not released yet…) for fun in spare time in the past day. I’m just trying to see how much I can get an ML-traditional syntax entirely within the Elixir AST, while being properly typed (with occasional fun with Refined Types and such). An example IEX session with it:

  • Basic Types (adding more over time)
iex> import MLElixir
MLElixir
iex> defml 1
1
iex> defml 6.28
6.28
iex> defml :ok
:ok
  • Let untyped variable bindings:
iex> defml let _a = 2 in 1
1
iex> defml let a = 1 in a
1
iex> defml let a = 42 in
...> let b = a in
...> let c = b in
...> c
42
  • Let Typed variable bindings (The errors are very simplistic and not descriptive right now, still debugging time after all):
iex> defml let ![a: int] = 1 in a
1
iex> defml let ![a: float] = 6.28 in a
6.28
iex> defml let a = 1 in
...> let ![b: int] = a in
...> b
1
iex> defml let ![a: int] = 6.28 in a
** (MLElixir.UnificationError) Unification error between `{:"$$TCONST$$", :float, [values: [6.28]]}` and `{:"$$TCONST$$", :int, []}` with message:  Unable to resolve mismatched types
    (typed_elixir) lib/ml_elixir.ex:566: MLElixir.resolve_types!/3
    (typed_elixir) lib/ml_elixir.ex:250: MLElixir.resolve_binding/3
    (typed_elixir) lib/ml_elixir.ex:163: MLElixir.parse_let/3
    (typed_elixir) expanding macro: MLElixir.defml/1
                   iex:16: (file)
  • Let Refined Typed variable bindings:
iex> defml let ![a: int a=1] = 1 in a
1
iex> defml let ![a: int a<=2] = 1 in a
1
iex> defml let ![a: int a>=2] = 1 in a
** (MLElixir.UnificationError) Unification error between `{:"$$TCONST$$", :int, [values: [1]]}` and `{:"$$TCONST$$", :int, [values: [{2, :infinite}]]}` with message:  Unable to resolve
    (typed_elixir) lib/ml_elixir.ex:566: MLElixir.resolve_types!/3
    (typed_elixir) lib/ml_elixir.ex:250: MLElixir.resolve_binding/3
    (typed_elixir) lib/ml_elixir.ex:163: MLElixir.parse_let/3
    (typed_elixir) expanding macro: MLElixir.defml/1
                   iex:6: (file)

Function calls (shown here via +):

iex> defml 1+2
3
iex> defml 1.1+2.2
3.3000000000000003
iex> defml 1+2.2
** (MLElixir.UnificationError) Unification error between `{:"$$TCONST$$", :int, [values: [1]]}` and `{:"$$TCONST$$", :float, [values: [2.2]]}` with message:  Unable to unify types
    (typed_elixir) lib/ml_elixir.ex:712: MLElixir.unify_types!/3
    (typed_elixir) lib/ml_elixir.ex:108: anonymous fn/3 in MLElixir.Core.__ml_open__/0
    (typed_elixir) lib/ml_elixir.ex:199: MLElixir.parse_ml_expr/2
    (typed_elixir) lib/ml_elixir.ex:145: MLElixir.defml_impl/2
    (typed_elixir) expanding macro: MLElixir.defml/1
                   iex:2: (file)

Opening (‘import’ in Elixir parlance) another module (also showing how to disable the Core opens, as you can see it is the Core that defines the + function):

iex> defml let open MLElixir.Core in 1+2
3
iex> defml no_default_opens: true, do: let open MLElixir.Core in 1+2
3
iex> defml no_default_opens: true, do: 1+2
** (MLElixir.InvalidCall) 6:Invalid call of `+` because of:  No such function found
    (typed_elixir) lib/ml_elixir.ex:196: MLElixir.parse_ml_expr/2
    (typed_elixir) lib/ml_elixir.ex:145: MLElixir.defml_impl/2
    (typed_elixir) expanding macro: MLElixir.defml/1
                   iex:6: (file)
132 13941 106

Most Liked

derpydev

derpydev

Sorry to be a bit off topic, but I feel like you missed an great opportunity in not calling this project ExML…ok I’ll show myself out now…

Seriously though awesome project!

josevalim

josevalim

Creator of Elixir

Reading this thread has been such an emotional rollercoaster. :joy:

To sum up, -> is only allowed between do/end, fn/end and (/). But you need to be careful because the parens need to apply to the -> and not arguments. The reason why foo(fun x -> x) does not work becomes clearer if you add multiple arguments. If you have foo(fun x, y -> x), does it mean foo(fun x, (y -> x)) or foo((fun x, y -> x))?

The reason I wrote the document linked by Eric is exactly because we wanted to show it is less rules than most would expect. Especially because we don’t need to specify the rules for keywords like case, def, defmodule, receive, if, try, etc.

ericmj

ericmj

Elixir Core Team

The difference between quote do fun x -> x end and defml fun x -> x is exactly the block. quote is not magically cheating in any way, the parser accepts -> in quote because it’s inside a block. When you call your defml macro you don’t wrap -> in a block.

If you use fn x -> x instead of fun x -> x you need to also end the block with an end since fn creates a block just like do.

It’s easy to remember what creates blocks in Elixir because there are only three ways to do it. do ... end, fn ... end and ( ... ). do blocks are in fact just sugar for ( ... ) and they are represented the same way in the syntax tree.

Check the “Blocks” section in the docs [1] for more details.

[1] https://hexdocs.pm/elixir/master/syntax-reference.html#syntax-sugar

Where Next?

Popular in Announcing Top

tmbb
PhoenixWS - Websockets over Phoenix Channels Source code on Github here: https://github.com/tmbb/phoenix_ws Phoenix channels are a great...
New
OvermindDL1
I created a new library (rather I pulled out a couple files from my big project), it manages an operating system PID file for the BEAM. ...
New
ityonemo
Currently just starting out on a new mini-project - getting zig NIFs to run in elixir. The idea here is to make the zig NIFs be “embed...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 43591 214
New
zorbash
I created Kitto a framework for dashboards inspired by Dashing. [demo] The distributed characteristics of Elixir and the low memory foo...
New
mbuhot
Leverage Open Api 3.0 (Swagger) to document, test, validate and explore your Plug and Phoenix APIs. Generate and serve a JSON Open API ...
New
aditya7iyengar
Rummage.Ecto and Rummage.Phoenix provide ways to perform Searching, Sorting and Pagination over Ecto queries and Phoenix collections. Fo...
New
Jskalc
Hi! Today, after a couple weeks of development I’ve released v0.1 of LiveVue. It’s a seamless integration of Vue and Phoenix LiveView, i...
New
Qqwy
TypeCheck: Fast and flexible runtime type-checking for your Elixir projects. Core ideas Type- and function specifications are const...
336 14302 100
New
anshuman23
Hello all, I have been working on my proposed project called Tensorflex as part of Google Summer of Code 2018.. Tensorflex can be used f...
New

Other popular topics Top

josevalim
Hi everyone, One of the features added to Elixir early on to help integration with Erlang code was the idea of overridable function defi...
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
gausby
I asked this very same question on twitter and got some interesting feedback, but I thought it would be a good question to ask here as we...
1207 39247 209
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
AngeloChecked
What learn first? Rust or Elixir Hi Elixir community! I’m here because i want learn a new language. I’m a junior developer and mainly i ...
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 35953 110
New
marick
I had some trouble figuring out how to make many-to-many associations work. Once I got it working, I wrote a blog post. Because I'm a nov...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New

We're in Beta

About us Mission Statement