Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update OR= to support unbound variables #158

Open
wants to merge 2 commits into
base: master
from

Conversation

Projects
None yet
3 participants
@shawwn
Copy link
Member

shawwn commented Feb 6, 2019

shawwn added some commits Feb 6, 2019

@akkartik

This comment has been minimized.

Copy link
Member

akkartik commented Feb 6, 2019

Could you update the title (and maybe description) with precisely what functionality is being added here? I know you link to the discussion, but I'm not confident I followed it entirely. Is it just supporting unbound variables? If so, it's interesting that the new implementation is nothing like the old one.

If I know what functionality is being added, I can go back and add more tests once this PR is merged.

@shawwn shawwn changed the title Update OR= Update OR= to support unbound variables Feb 6, 2019

@rocketnia

This comment has been minimized.

Copy link
Member

rocketnia commented Feb 6, 2019

Hmm, I'm not confident with that approach -- I think setforms oughta be in control of performing ssexpansion -- but my first stab at it would have issues of its own:

 (mac or= (place expr)
   (let (binds val setter) (setforms place)
     `(atwiths ,binds
-       (or ,val (,setter ,expr)))))
+       (or (errsafe ,val) (,setter ,expr)))))

In official Arc, maybe that would be fine, but in Anarki, it's possible for variable names to perform complex behaviors when they're evaluated, so they might throw exceptions for reasons other than being unbound.

I feel like a proper approach to this would involve refactoring how setforms works, which I don't think is worth it for this. What you have is probably good.

@akkartik

This comment has been minimized.

Copy link
Member

akkartik commented Feb 6, 2019

👍 to the title change.

@shawwn

This comment has been minimized.

Copy link
Member Author

shawwn commented Feb 6, 2019

Yeah, I think it's just unbound variable support.

As for the implementation, I lifted it from laarc. I didn't know arc already had an or=. But I know this one works. :)

I attempted to make anarki reloadable in this commit: 7ed7d12

@rocketnia

This comment has been minimized.

Copy link
Member

rocketnia commented on apps/news/news.arc in 7ed7d12 Feb 6, 2019

Hmm, this is a very ironic thing to see. If some of the global state values are actually going to be legitimate empty lists, it seems like a bad idea to use or= to decide whether to set them. Then again, setting them to another empty list doesn't cause a problem; this would only be a problem if the default value were a non-empty list and it could legitimately become empty later.

This comment has been minimized.

Copy link
Member Author

shawwn replied Feb 6, 2019

Mm, I don't think that can happen. If it's a non-empty list and uses or= to initialize itself, then there's no situation where it can legitimately become empty at load time.

This comment has been minimized.

Copy link
Member

rocketnia replied Feb 6, 2019

I suppose this may also affect booleans which have a default value of t and get set to nil later, if any cases like that come up.

This comment has been minimized.

Copy link
Member

akkartik replied Feb 6, 2019

@shawwn I think Ross is describing the following scenario:

First load: (or= x '(1 2 3))

During server running: (= x '())

Next load: (or= x '(1 2 3))

You end up reverting x.

I remember now that considerations like this (particularly with boolean flags) led me in Readwarp to decouple variable value from whether the variable is currently bound or not.

This comment has been minimized.

Copy link
Member Author

shawwn replied Feb 6, 2019

Ah.

Does that ever happen?

This comment has been minimized.

Copy link
Member

akkartik replied Feb 6, 2019

With booleans certainly. And in any case it feels like a gotcha. I think "avoid reloading" is a separate concern from or=, and it's tempting but wrong to conflate the two. Still worth adding this ability, but we should keep it separate.

In Readwarp the top-level forms I had for defining global variables were =, const, init and inittab. You can find them linked from http://arclanguage.org/item?id=21150.

This comment has been minimized.

Copy link
Member

rocketnia replied Feb 6, 2019

I was about to suggest init for this too. I think it's a great name for this.

@rocketnia

This comment has been minimized.

Copy link
Member

rocketnia commented Feb 6, 2019

Oh, I just realized another thing about this that isn't quite right: The design of setforms makes it so in operations like (or= ((...) (...)) 42), the (...) expressions only get evaluated once. This change causes or= to evaluate those expressions more than once.

@rocketnia

This comment has been minimized.

Copy link
Member

rocketnia commented Feb 6, 2019

Hmm, I'm sorry I seem to be rattling off a lot of different comments in a disorganized way today, but another thing comes to mind:

Your implementation uses (or (if (bound ',slot) ,slot) ...), but (bound ',slot) checks whether something is bound in the global scope, not the local scope. Honestly, it's hard for Arc macros to check for bindings in the local scope until we give them access to env, so this weaves into a lot of the other topics we've been talking about.

@shawwn

This comment has been minimized.

Copy link
Member Author

shawwn commented Feb 6, 2019

This change causes or= to evaluate those expressions more than once.

Interesting. Could you give an example?

@shawwn

This comment has been minimized.

Copy link
Member Author

shawwn commented Feb 6, 2019

(bound ',slot) checks whether something is bound in the global scope, not the local scope

Good point! This should get resolved with the env changes from #151

@rocketnia

This comment has been minimized.

Copy link
Member

rocketnia commented Feb 6, 2019

This change causes or= to evaluate those expressions more than once.

Interesting. Could you give an example?

I haven't tested this yet, but try this:

(= foo (table))
(or= ((do (prn "hello") foo) (do (prn "world") 'bar)) 'baz)

I think the current or= will only print "hello" and "world" once, but I think yours will print them twice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.