janet-lang / janet

A dynamic language and bytecode vm
https://janet-lang.org
MIT License
3.38k stars 217 forks source link

Proposal: Terse Chained Indices #1395

Closed ghost closed 3 months ago

ghost commented 5 months ago

EDIT: @pepe has a better idea, see below.

> (def lookup {:a 1 :b {:c 3}})
{:a 1 :b {:c 3}}
> (lookup :b :c)
3

That's the idea. Nested tables are common as dirt in APIs, so can stand to be streamlined; dot notation chains naturally, but tuple notation is a bit awkward without tricks. This is technically "magic", but not significantly more so than what we already have.

sogaiu commented 5 months ago

Is this similar to (get-in lookup [:b :c])?

ghost commented 5 months ago

Yes, it's identical in functionality when the keys exist. On missing keys or non-indexable values, to me it makes the most sense to match current ((lookup :b) :c):

> (lookup :c)
nil
> (lookup :c :d)
error: attempt to index a nil value: (lookup :c) = nil
> (lookup :a :e)
error: attempt to index an integer: (lookup :a) = 1

Kind of syntax sugar, except there's no new concepts being introduced; rather an existing one is being elaborated. So more like chemically modifying the syntax to sweeten it.

pepe commented 5 months ago

I guess there will be a performance penalty on every lookup with just one key, as the in function (under the hood, if I am not mistaken) will always need to allocate variadic params tuple.

But I like the idea. What about . macro, which works as https://github.com/janet-lang/spork/blob/master/spork/misc.janet#L396 but with in so we can (. lookup :c :d)?

ghost commented 5 months ago

Message ID: @.***>Huh, is . really not taken yet? Yeah, that sounds good. It's hard to argue with performance.

sogaiu commented 5 months ago

I wonder if there isn't code out there that uses . for their own purposes...

I'm also not so in to additional shortcuts (including a lot of user-defined macros) because I think it tends to increase the learning burden of the reader (which in turn can lead to additional costs for investigation and maintenance). One of the reasons I like lisp-likes is so I don't have to remember / learn so many exceptions.

I'm probably in the minority though (as someone who's not in to things like (1 @[:a :b :c]) (^^;

pepe commented 5 months ago

I feel your pain, @sogaiu <3. But dot notation is evoked by this syntax, so even you will be OK.

pepe commented 5 months ago

If it ever gets considered, that's it.

ghost commented 5 months ago

Hm. That is a potential issue. I can't imagine what else . would be used for but I can definitely see it being used. I guess we could grep "\(((def|var) |defn \()\." on some decent-sized projects to assess the damage. (I don't have machine for that atm.)

Also I'm with you, I dislike (<int> <array>). What is this, cc -O0?

sogaiu commented 5 months ago

I'm not sure of a good way to express an appropriate search -- the grep example given lacks checking for defmacro, defmacro-, and other constructs. Also, people define their own defining constructs which may then be used to define further things...

In any case, if you want to do some spelunking, this list is close to what I know about. Likely there is more stuff out there (^^;


Re: (<int> <array>) - I think this kind of thing is not that odd if one allows keyword lookup like (:a {:a 1 :b 2}) (I'm not a huge fan of that either, but it's done in at least one other lisp-like IIUC).

ghost commented 5 months ago

Message ID: @.**>I just thought of one: \(\. | \.( |\)) catches all uses* of . as a symbol, regardless of how it's defined.

Also, damn @pepe, you really want to hoard all the puns? I think what I'm feeling is...sadness :^(=>{=

iacore commented 5 months ago

I use plain syntax because the term can be put inside (set).

(def lookup @{:a 1 :b @{:c 3}})
(set ((lookup :b) :c) 4)
lookup 
# => @{:a 1 :b @{:c 4}}

This macro generates the same plain syntax.

(defmacro .
  "Recursive macro (ds key)."
  [ds & keyz]
  (reduce (fn [t key] (tuple t key)) ds keyz))
pepe commented 5 months ago

@im-not-linja I am sorry to make you sad, even as I am not sure what you meant by the accusation. Can you please elaborate? Maybe DM Zulip so as not to pollute the discussion here.

sogaiu commented 4 months ago

FWIW, there was mention from someone on one of the janet-language matrix channels that they are using . in something they are working on.

bakpakin commented 3 months ago

Closing as I prefer the . macro. Chained lookup is useful, but there are deeper ramifications for modifying the behavior of in and get.

ghost commented 3 months ago

Yeah, you're right, it's a much better idea.

pepe commented 3 months ago

@im-not-linja, I am still in limbo with all the puns I stole. I could indeed be a thief in some situations, but I am usually aware of it. Could you please elaborate?

ghost commented 3 months ago

Oh wow, @pepe, sorry, I really didn't expect you to take that seriously at all. It was a joke about your projects spanning every name in the series, so no one else could follow the common naming pattern of referencing the same thing the name of the language/framework/whatever is referencing. Really, utterly inconsequential. (The latter sentence is Janet's line in the signoffs from The Good Place: The Podcast season 1, and then my best Janet emoticon.)

pepe commented 3 months ago

I had that feeling, but I wanted to be sure. Just so you know, I will deprecate all the standalone libraries and keep only gp (as the abbreviation of Good Place), so all the names will be free to grab :–).

ghost commented 3 months ago

Wow, ok. Thanks Doug.