samth
2017-11-27 23:04:58

egads, someone doing metaprogramming nicer than racket! https://docs.rs/structopt-derive/0.1.5/structopt_derive/


apg
2017-11-28 00:00:42

is that nicer ?


samth
2017-11-28 00:01:41

@apg the syntax is pretty ugly, but it’s getting a lot more than what we do for cmd line options


samth
2017-11-28 00:01:56

in particular, auto-parsing from the struct definition


apg
2017-11-28 00:02:35

just requires rolling up the sleeves and doing the work though. :slightly_smiling_face:


lexi.lambda
2017-11-28 00:02:35

I’ve wanted that for a while, fwiw. Haskell has optparse-generic, which does a similar thing.


lexi.lambda
2017-11-28 00:03:01

But this is all way nicer with ~~typeclasses~~ because you can use the type information to know how to parse each field. :)


lexi.lambda
2017-11-28 00:03:15

(And Rust has traits, which I imagine can do the same thing here.)


samth
2017-11-28 00:05:09

yeah


samth
2017-11-28 00:05:24

plus annotations on struct fields


apg
2017-11-28 00:05:58

annotations on struct fields would be great


notjack
2017-11-28 00:44:59

@lexi.lambda oh I’ve been meaning to ask you: what approaches to hackett’s type-value namespaces didn’t work?


lexi.lambda
2017-11-28 01:00:16

@notjack I tried a few slightly different things before I got something work, but most of the dramatically different things that wouldn’t have worked I dismissed without trying


lexi.lambda
2017-11-28 01:01:43

I think the most significant difference between my first attempt and the current implementation is that I originally tried having different type/value scopes per module instantiation, but that ended up being needlessly complicated.


lexi.lambda
2017-11-28 01:02:44

the only remotely plausible alternative approach I thought about was to use phases instead of scopes, but that didn’t really hold up to scrutiny.


notjack
2017-11-28 01:10:39

I’m wondering if using the same approach within a module but doing one of the following instead of name mangling might work:

  • Providing from one of either a value-namespace or a type-namespace submodule, with hackett’s require looking for those submodules and adding type/value scopes to imports based on which submodule they came from (maybe the parent providing module should provide the scope introducer functions it used as well? not sure)
  • Providing syntax bound to a struct containing a field for a value identifier and a field for a type identifier, each having their type/value scope already added, with hackett’s require recognizing these bindings and unpacking them.

But I don’t know how much work either of those would take to make them cooperate with scribble.


lexi.lambda
2017-11-28 01:11:57

The problem with both of those approaches is that it makes it very difficult to make them transparently work with require and provide.


lexi.lambda
2017-11-28 01:12:30

Specifically, you want to be able to do things like (require (rename-in [Tuple tuple])) and have it only rename the value-level Tuple.


notjack
2017-11-28 01:13:04

that’s already rather painful no? You have to rename-in the #%hackett-type:id form


lexi.lambda
2017-11-28 01:13:06

So packing things together doesn’t really work. And you can’t easily lift the appropriate values into submodules when to do provide.


lexi.lambda
2017-11-28 01:13:48

It might work if you did the packing with an entirely custom provide form?


notjack
2017-11-28 01:14:30

what other kinds of requires get painful besides rename-in?


lexi.lambda
2017-11-28 01:14:36

The trouble is that require can only be customized so much… you can’t make a require introduce a new syntax binding.


notjack
2017-11-28 01:14:50

oh dang you can’t?


lexi.lambda
2017-11-28 01:15:28

No, provide transformers can lift, but they can’t expand to a definition.


notjack
2017-11-28 01:16:13

hm wait


lexi.lambda
2017-11-28 01:16:45

I think I tried hacking something with syntax-local-lift-module, but IIRC the lifted module isn’t available when the require is expanded, so you can’t require it in the expansion.


notjack
2017-11-28 01:17:40

confused about which of these is possible:

  • provide transformer introduces new normal binding and exports it
  • provide transformer introduces new syntax binding and exports it
  • require transformer binds and declares import of new normal binding
  • require transformer binds and declares import of new syntax binding

and which lift functions are used for this? just syntax-local-lift-* stuff or things that are specific to require/provide?


lexi.lambda
2017-11-28 01:19:43

Yeah, it’s syntax-local-lift-*. And note that provide pre-transformers can lift, but provide transformers can’t… and only provide transformers have access to the set of bindings imported/exported when doing something like (provide (all-from-out foo/bar/baz)).


notjack
2017-11-28 01:20:36

also: do these require/provide limitations have good reasons for existing, or could some patches to the require/provide system implement them without much issue?


lexi.lambda
2017-11-28 01:21:18

I looked at the source code for Racket’s require and provide, and I examined #%require and #%provide a little.


lexi.lambda
2017-11-28 01:21:41

Here’s what I learned: require transformers and provide pre-transformers are implemented in Racket. Provide transformers are implemented in C.


lexi.lambda
2017-11-28 01:23:02

I think provide transformers are pretty restricted because they have access to the bindings exported by all-from-out and things like that, but in order to know that, the module needs to know which bindings are shadowed by the module body. So provide transformers are essentially the very last step of macro transformation in a module’s expansion.


lexi.lambda
2017-11-28 01:23:31

This is a bit tricky, since it means provide transformers can’t do any lifting, but it means provide pre-transformers can’t know the precise set of bindings being exported.


lexi.lambda
2017-11-28 01:31:13

Require transformers can do pretty much anything by comparison, but “anything” is restricted by the fact that it can only expand to #%require clauses and lift things. That restriction could probably be lifted, providing some API to make a require transformer expand to a fresh definition? But you’d have to be careful, since an imported definition could be hidden with only-in or something similar.


notjack
2017-11-28 01:33:09

commuting; will read in more detail later. Off the cuff thought: wondering if the racket implementation of the macro system will make changes here possible / easier


lexi.lambda
2017-11-28 01:34:11

The provide restrictions are semi-fundamental AFAICT, and require transformers are already implemented entirely in Racket, so my gut says “no”, but it’s possible I am being insufficiently creative.


slack1
2017-11-28 07:06:44

I would be curious one day to see an indentation-based Lisp


slack1
2017-11-28 07:06:54

A Lisp with minimal parens!


slack1
2017-11-28 07:08:03

I notice that Lisp users kind of already have an indentation-based organization



brendan
2017-11-28 07:09:52

It looks like that was a scheme proposal


brendan
2017-11-28 07:10:23

brendan
2017-11-28 07:10:50

where have I seen infix curly brace notation :thinking_face:


slack1
2017-11-28 07:14:21

Hmm most results look more readable in srfi 110


slack1
2017-11-28 07:14:24

Some are mixed results


brendan
2017-11-28 07:18:02

My biggest issue is when switching back to a lisp after writing in languages with more typical syntax


brendan
2017-11-28 07:18:46

Like earlier today, when I mixed up (<= 1) and (lambda [x] (<= x 1)), because Hackett’s partial applications look like Haskell’s operator sections