Comments (16)
Can you please explain dot operator (?) here:
https://github.com/janet-lang/janet/blob/master/examples/life.janet#L19
And here:
https://github.com/janet-lang/janet/blob/master/examples/life.janet#L27
from janet.
The dot operator is like an array indexing operator. An expression a.b
is treated by the compiler much like (get a b)
. The colon operator works with keywords. An expression a:b
is treated by the compiler like (get a :b)
.
In some older version of janet, the dot operator was able to index with integer keys. In other words, you could do a.0
to get the first element of a tuple. I have removed that for now because I did not want to commit to the syntax, but I think it might be useful.
from janet.
The old behavior was removed as I was making some large changes to Janet internals about representation of integers. I have added it back with the latest commit 29ec30c. You should now be able to do things like
(var a @{})
(set a.0 :hi)
(print a.0) # prints :hi
from janet.
Hm.. Can we just disallow numeric keywords like :14
and then fetch indexes with same syntax.
a:14 => get item with index 14 from a (or key 14 if a is a dict)
a:cat => get item with key :cat from dict a
a:"baa" => get item with key "baa" from dict a
Think indexed container is a dict with integer keys only.
Update: Oh! Symbols can be used as keys. a:cat
will fetch value with symbol-key cat.
Syntax example using "folder" notation:
a/14 => get item with index 14 from a (or key 14 if a is a dict)
a/cat => get item with symbol-key cat from dict a
a/:cat => get item with key :cat from dict a
a/"baa" => get item with key "baa" from dict a
Modules can be done in same fashion. As they already using this syntax.
from janet.
I'll have to think about this some more. I agree that the current syntax is not general enough, but I also don't want to complicate the parser too much, nor incur a table lookup at runtime for using module functions.
I like the current way of handling modules by just merging the symbols from the loaded module into the current environment because it allows really flexible imports like (import mymodule :prefix "")
, which is like clojure's use
(I realize this isn't well documented yet).
Right now, these shorthand syntax's are done in the compiler on a single symbol. This means that to the parser, all of these notations are just one symbol.
(type 'a:b) => :symbol
(type 'hello.1) => :symbol
I think that this functionality should be in the parser, and the compiler doesn't need to know anything about the syntax. The set
special form will still need to know how to act like a put
, however. After
the parser creates a tuple, the runtime would need to treat data structures as functions that look up keys.
Some ideas:
a:b => (a b) or (a :b) or maybe (get a b)
a.b.c.d => (a b c d) or maoybe (get a b c d)
a.b.c.1.2 => (a b c 1 2) or (a b c 1.2)?
a/"hello"/1.2e4/0x45 => (a "hello" 1.2e4 0x45)
a|b|"c"|:d => (a b "c" :d)
All of these have issues. Using a colon means keyword keys become different. A period is a valid
character in a number, so one could not have fractional numbers in such a form. The forward slash /
is currently the division function. The pipe |
wouldn't have any collisions, but it looks a bit strange.
All together I think it would take several changes to get this to work as smoothly as possible. I think the steps would be
- Allow calling data structures as functions.
- Update parser to support some infix tuple syntax
- Update set special form to take a tuple returned by the parser as an lvalue.
This also has the benefit that each of these three steps is a useful feature on its own.
from janet.
Agree!
But it needs to be made in simple but powerful form. This is Lisp! :)
My thoughts on some nested dict:
(((dict-1 key-a) key-b) key-c)
can be shorten
(@ dict-1 key-a key-b key-c)
No extra syntax involved.
from janet.
But it needs to be made in simple but powerful form. This is Lisp! :)
You're right, maybe simpler is better.
I have also been thinking about your "folder" notation, and I quite like it, regardless of whatever character becomes the delimiter. It would also make nested gets really easy as well.
a/b => (a b)
a/b/c => ((a b) c)
from janet.
The latest commit now has working symbols, keywords, and data structures as functions.
(:a {:a 1}) # 1
({:a 1} :a) # Also 1
I have been working on a lot of changes internal to the interpreter to simplify things a bit and deleting many lines of code. The external API should not have changed but be warned.
Also I have had a thought about how the set special could change. Perhaps the set special could take an lvalue that looks like the form that will retrieve the value like setf in other lisps, and remove the current shorthand. An example:
(def tab @{})
(set (tab :a) 1)
from janet.
Yay! Interesting, bi-directional logic here.
As I understand nested access will look like this:
((( {:a {:b {:c 1}}} :a) :b) :c) # 1
And can be simplified by macro.
Love your choice towards simplicity.
from janet.
Yes, set
form will work using same (getter) syntax.
from janet.
Seems number and string types can be added to funclike too:
# arg access (all ok!)
janet:675:> ({'a 1 'b 2} 'b)
2
janet:692:> ({:a 1 :b 2} :b)
2
janet:709:> ({"a" 1 "b" 2} "b")
2
janet:729:> ('(1 2) 1)
2
# call access (number and string fails)
janet:740:> ('b {'a 1 'b 2})
2
janet:757:> (:b {:a 1 :b 2})
2
janet:774:> ("b" {"a" 1 "b" 2})
error in repl: attempted to call "b", expected function|cfunction
(fiber)
in _thunk [repl] at (775:793) (tailcall)
janet:794:> (1 '(1 2))
error in repl: attempted to call 1, expected function|cfunction
(fiber)
in _thunk [repl] at (795:804) (tailcall)
from janet.
I think, basically, this condition can be removed, janet_get will error back:
Lines 226 to 229 in 6f3bc3d
Then there is no need for funclike. Or it is better to set funclike = indexed | dictionary. As they are actually callables here.
Line 231 in 6f3bc3d
from janet.
My thought was that not everything should be callable as a function as it might hide errors, but playing
around with it it seems that there is no issue. In fact it seems being able to call nil is useful in certain cases, like in looking values up in a map.
Updated in 2a79d2e.
from janet.
There is an idea to interpret "call" access as a call:
janet:24:> (def obj {:wof (fn () (print "wof-wof"))})
{:wof <function 0x00574D80>}
# call access
janet:63:> (:wof obj)
wof-wof
nil
# arg access
janet:74:> (obj :wof)
<function 0x00574D80>
Pretty useful hack, but little complicated. What do you think?
from janet.
Its an interesting idea. When combined with table prototypes one could implement a very effective yet lispy OO paradigm with prototypical inheritance. Perhaps the function could receive obj
as the first argument.
# Create a 'class'
(def Car @{:honk (fn [self] (print "I am a " (self :maker)))})
# Create an 'instance'
(def mycar (table/setproto @{:maker "Subaru"} Car))
# Make a 'method call'
(:honk mycar)
I think an implementation could be made relatively simple and be efficient as well, which is a plus.
I had been playing around various ways of implementing OO before non-function types were callable,
and this seems better.
Edit: This should be a separate issue though
from janet.
Yep! Closing.
from janet.
Related Issues (20)
- `empty?` should be documented more clearly. HOT 2
- Document how `os/spawn` should be cleaned up or handle zombie processes... HOT 40
- The case for a context object HOT 2
- The default meson option `epoll=false` causes a busy loop and segmentation fault. HOT 10
- Proposal: Terse Chained Indices HOT 19
- Reimplement `slurp` with `os/open`. HOT 28
- A way to read standard input in the background without `file/read` in a thread. HOT 4
- `each` macro improper behavior? HOT 8
- `if-let` breaks tail call optimization. HOT 6
- false branch of `if-let` doesn't report the correct call stack information. HOT 4
- `ev/select` should not resume a dead task. HOT 4
- `try` and `defer` break tail call optimization. HOT 4
- `(= @"update" @"update")` is `false`. HOT 3
- `ev/select` still revives fibers.... HOT 2
- option to unbundle docstrings and potential consequences HOT 8
- splicing into structs/tables HOT 2
- Disasm/asm doesn't round-trip for function with unused argument HOT 1
- eventloop/networking gets stuck on musl HOT 11
- Consider making `module/paths` a dynamic variable HOT 6
- Can it run on iOS? Thank you. HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from janet.