Re: [racket-users] Generate function defintions at compile time

2017-08-28 Thread Matthias Felleisen

> On Aug 28, 2017, at 4:24 AM, Konrad Hinsen  wrote:
> 
> I found the implementation of the Video language on pkg.racket-lang.org, but 
> neither Typed Video nor Docu Video seem to be there. Are they available 
> elsewhere? I am particularly interested in Docu Video because I wonder if it 
> can be implemented as a composition of "Video" and "Scribble" or if it needs 
> to be defined from scratch, re-using only the implementation modules of 
> "Video" and "Scribble".


Video Lang is Leif Andersen’s [CCed] project. I think ‘lang.video’ will become 
the actual site for the language, and you may want to watch it there. He has 
created updates, and I am sure the documentation language will make it to the 
repo/web site. 

Stephen created Typed Video as a demonstration project and as a teaser for the 
ICFP academic community (who is obsessed with types). None us actually thinks 
that a scripting language needs this kind of fancy type system. If you are 
interested in taking over, I am sure Stephen can sketch out what it takes to 
stay uptodate with Leif’s progress. 

— Matthias

p.s. Do check out the CACM paper, which is a high-level, non-academic sketch of 
the same idea, appealing to Video Lang along the way. 

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Generate function defintions at compile time

2017-08-28 Thread Konrad Hinsen

Matthias,


If you would like to see a concrete example, fully worked out, see the ICFP 
paper on constructing a domain-specific language for scripting the production 
of videos (say RacketCon presentations):

  https://www2.ccs.neu.edu/racket/pubs/#icfp17-dnff

At the surface, this could be done as a piece of two modules: the surface 
language (boring) and the run-time library that connects to existing NLVE 
systems. But as it turns out, if you truly take the slogan seriously, you can 
easily see how we build this application as a composition of EIGHT (8) DSLs, 
three used at the surface (Video, Typed Video, and Docu Video) and five below, 
inside the application.


This is really a nice illustration of "The Racket Way". Please consider 
pointing to this on the Racket Web site. Or, better yet, put a less 
academic writeup on this example to the Web site.


I found the implementation of the Video language on pkg.racket-lang.org, 
but neither Typed Video nor Docu Video seem to be there. Are they 
available elsewhere? I am particularly interested in Docu Video because 
I wonder if it can be implemented as a composition of "Video" and 
"Scribble" or if it needs to be defined from scratch, re-using only the 
implementation modules of "Video" and "Scribble".


Konrad.

--
You received this message because you are subscribed to the Google Groups "Racket 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Generate function defintions at compile time

2017-08-24 Thread Matthias Felleisen

> On Aug 24, 2017, at 9:38 PM, Alex Harsanyi  wrote:
> 
>  Its all just objects, functions and function applications supported by some 
> library code.  I could write a "#lang workout" with some macros to hide the 
> actual mechanism to make it look more "magic", but I don't see a value in 
> doing that.


Then don’t and live happily with functions and objects ever after. 

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Generate function defintions at compile time

2017-08-24 Thread Alex Harsanyi
On Thursday, August 24, 2017 at 9:42:51 PM UTC+8, Matthias Felleisen wrote:
> 
> Yes, Racket is a good language. But let me point you to the blog of a 
> reflective developer, and I consider reflective developers the best of their 
> kind: 
> 
>   
> https://medium.com/@daveford/80-of-my-coding-is-doing-this-or-why-templates-are-dead-b640fc149e22

None of the work that I do could be described, as the blog author puts it, 
"writing code in one language (say Java or JavaScript) whose sole purpose is to 
generate a different language (say HTML)".  This might affect my view of the 
world...

Sill, if I understand the article correctly, the author suggests that people 
should use DLS's *not* that they should write their own.

I was trying to make the argument that people starting using Racket should not 
be encouraged to solve simple problems by writing their own DSL, so I'm not 
sure the blog post disagrees with this.

For the record, I also agree that DLS's, as written by experienced people, are 
valuable and should be used by everyone.

> If you would like to see a concrete example, fully worked out, see the ICFP 
> paper on constructing a domain-specific language for scripting the production 
> of videos (say RacketCon presentations): 
> 
>  https://www2.ccs.neu.edu/racket/pubs/#icfp17-dnff
>

I admit that I only skimmed the article, it is after all 27 pages long :-), 
however this video DSL is written by experts, not by people who started using 
Racket last week.

Looking at the code example in the paper, it seems to me that the definition of 
a DSL is a bit different than mine.  In particular, it is not clear to me when 
a collection of library functions becomes a DSL.

For example, I have some Racket code that allows me to generate FIT workout 
files for Garmin devices (these are binary files that encode information about 
a structured running or cycling workout).  With the library, I can create 
workouts like this:

(require "al-workouts.rkt")
(define (hr/warmup) (hr/bpm 60 163))  ; Z1 + Z2
(define (pace/hard) (speed (pace 4 29) (pace 4 0)))   ; Z5 + 
(define (pace/easy) (speed (pace 7 32) (pace 5 7)))   ; Z1 and Z2 

(define (wk-daniel-q3)
  (define wk (new fit-workout-file% [name "daniel-q3"] [sport 1]))
  ((workout
(step (minutes 20) (hr/warmup) warmup)
(repeat 
 4  ; times
 (step (kms 1.2) (pace/hard) active)
 (step (minutes 4) (no-target) recover))
(step (lap-button) (pace/easy) cooldown))
   wk)
  (send wk get-fit-data))

(wr "daniel.q1.fit" (wk-daniel-q1)) ; write binary data to file

Is this a DSL?  Its all just objects, functions and function applications 
supported by some library code.  I could write a "#lang workout" with some 
macros to hide the actual mechanism to make it look more "magic", but I don't 
see a value in doing that.

Best Regards,
Alex.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Generate function defintions at compile time

2017-08-24 Thread Matthias Felleisen

> On Aug 23, 2017, at 9:49 PM, Alex Harsanyi  wrote:
> 
> As someone who managed to write a 3 like Racket application without using 
> macros, I think they are overrated for application development.  Macros are a 
> powerful and necessary feature for designing or extending a language, but 
> most people are better served by just using existing, well documented 
> languages.
> 
> I think Racket is a really good language and can be directly used to write 
> useful applications.  Yet new users are encouraged to start using the most 
> difficult to understand feature of Racket for their simplest of projects.


Yes, Racket is a good language. But let me point you to the blog of a 
reflective developer, and I consider reflective developers the best of their 
kind: 

  
https://medium.com/@daveford/80-of-my-coding-is-doing-this-or-why-templates-are-dead-b640fc149e22

This write-up is completely unrelated to Racket, but like many others out 
there, this developer has recognized an essential idea that is emerging in the 
world of sw dev: 

  problems are best solved on their own terms 
  and that is best done with a multitude of 
  languages — but all these languages must live
  in the same ecosystem so that it is easy to 
  glue the problem-specific components together. 

This, in essence, is also the Racket manifesto 
(http://www.ccs.neu.edu/home/matthias/manifesto/) also available as a PDF 
article for CACM (http://www.ccs.neu.edu/home/matthias/Tmp/cacm.pdf preferred 
version). 

If you would like to see a concrete example, fully worked out, see the ICFP 
paper on constructing a domain-specific language for scripting the production 
of videos (say RacketCon presentations): 

 https://www2.ccs.neu.edu/racket/pubs/#icfp17-dnff

At the surface, this could be done as a piece of two modules: the surface 
language (boring) and the run-time library that connects to existing NLVE 
systems. But as it turns out, if you truly take the slogan seriously, you can 
easily see how we build this application as a composition of EIGHT (8) DSLs, 
three used at the surface (Video, Typed Video, and Docu Video) and five below, 
inside the application. 

Like Neil, I don’t have any good metric other than “lines of code 
eliminated/never written”. Based on my personal experience, I find uses for 
small DSLs or at least bundles of macros everywhere. My most recent example is 
the construction of a test suite for a distributed board game project. I 
noticed that I was writing a lot of variations of setup/test/tear-down that 
were reasonably compact (say 10-15 lines per unit test) but hardly readable. So 
I rewrote it with a DSL that allowed me to articulate each test as a 
description of a game scenario. I demoed it to my class, made up of students 
who do not know Racket. I showed the test suite, I explained the cases for a 
particularly difficult aspect, and a student spotted a missing corner case. The 
class was able to dictate the missing test case to me — and of course the code 
broke. (It was also fixable in about 2 minutes.) If I had demoed the rackunit 
cases, they would not have been able to formulate the test case — because they 
simply don’t know (enough) Racket. 

Time to think — Matthias


-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Generate function defintions at compile time

2017-08-23 Thread Philip McGrath
On Wed, Aug 23, 2017 at 8:49 PM, Alex Harsanyi 
wrote:
>
> I think Racket is a really good language and can be directly used to write
> useful applications.  Yet new users are encouraged to start using the most
> difficult to understand feature of Racket for their simplest of projects.
>

At the risk of going off topic, I would not consider macros the most
difficult to understand feature of Racket (especially given the competition
from continuations, various concurrency and parallelism constructs,
namespaces and eval, inspectors ...). I found syntax-rules style macros a
fairly easy step from the style of reasoning about evaluation by
substitution of expressions encouraged by HtDP. And syntax-parse makes it
easy to address robustness concerns.


> > `prefix-in` is an old kludge for an old idea that, AFAIK, is no longer
> > considered as good an idea as it used to be.


I don't object to prefix-in sometimes, but I would not recommend writing
modules in the style of parser-tools/lex-sre (which re-defines things like
+) or those documented under
http://docs.racket-lang.org/web-server-internal/dispatchers.html (which
each export a function named make, even though you will almost always want
the make function from more than one such module, making them virtually
unusable without prefix-in or rename-in).

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Generate function defintions at compile time

2017-08-23 Thread Neil Van Dyke



As someone who managed to write a 3 like Racket application without using 
macros, I think they are overrated for application development.  Macros are a 
powerful and necessary feature for designing or extending a language, but most 
people are better served by just using existing, well documented languages.


DSLs/minilanguages are, like, kinda a big deal.  And Racket has perhaps 
the best support for them.


I think it should be normal for a Racketeer to spend some time getting 
comfortable with DSLs/minilanguages, so that they can start to recognize 
when a DSL/minilanguage is a big win.


Regarding macros, syntax transformation happens to often be a great way 
to implement DSLs/minilanguages efficiently in Racket.  Shifting 
computation to compile phase is not the only use of macros, but it's 
relevant here.


I and many other people speak loosely about relative merits of different 
programming practices, but we don't actually have great metrics for most 
of that.  Lines-of-code (SLOC) metrics, for example, are most useful for 
saying things like "We refactored, with judicious use of macros and 
other accepted programming practices, and incidentally cut the million 
lines down to 200K." and "A hundred million lines of code?!  I don't 
think we can QA that in 3 months." Despite poor metrics, I'm happy to 
occasionally and generously share my own opinions, and to sniff 
dismissively at other people's opinions, in the time-honored tradition 
of programming language forums elsewhere.


--
You received this message because you are subscribed to the Google Groups "Racket 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Generate function defintions at compile time

2017-08-23 Thread Alex Harsanyi
On Thursday, August 24, 2017 at 8:59:26 AM UTC+8, Neil Van Dyke wrote:
> h...@oorg wrote on 08/23/2017 06:56 PM:
> 
> > Wouldn't making a DSL be overkill?
> 
> No.  In Racket, a DSL (aka minilanguage, syntax extensions, or macros) 
> can be a very small implementation effort that does exactly what one 
> wants, in a very maintainable way.

As someone who managed to write a 3 like Racket application without using 
macros, I think they are overrated for application development.  Macros are a 
powerful and necessary feature for designing or extending a language, but most 
people are better served by just using existing, well documented languages.

I think Racket is a really good language and can be directly used to write 
useful applications.  Yet new users are encouraged to start using the most 
difficult to understand feature of Racket for their simplest of projects.

> > Isn't this the sort of thing that should be handled by `prefix-in`?
> 
> `prefix-in` is an old kludge for an old idea that, AFAIK, is no longer 
> considered as good an idea as it used to be.  

Do you have any references for this statement?

I personally prefer short function names that I can prefix as needed versus 
littering my code with "author-package-foo" function calls.

Is 'prefix-in' a deprecated feature?

Best Regards,
Alex.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Generate function defintions at compile time

2017-08-23 Thread Neil Van Dyke

hiph...@openmailbox.org wrote on 08/23/2017 06:56 PM:


Wouldn't making a DSL be overkill?


No.  In Racket, a DSL (aka minilanguage, syntax extensions, or macros) 
can be a very small implementation effort that does exactly what one 
wants, in a very maintainable way.



Also, I don't have a choice in the matter how the API data is stored, a hash 
table is what I receive.


You're already running contrived Racket code to generate the hash syntax 
that you paste into the source file.  So you can alternatively paste 
slightly different contrived syntax, if that gives you an advantage.  
(Initially, because you happened to paste a Racket hash syntax into that 
file, you were making your life a lot harder than it needed to be.)



The API is only a part of the library, there is also the "client" (connecting to a Neovim 
instance) and the Racket "host" (allowing Neovim plugins in Racket). I might later 
re-export the bindings from `nvim/api` through `nvim`, I haven't decided on that yet.


This is getting into reuse ecology questions.  For now, you might just 
ask yourself whether this all needs to be in one package.  And, if 
multiple packages, just use the respective package name as the reusable 
`require` name.



Isn't this the sort of thing that should be handled by `prefix-in`?


`prefix-in` is an old kludge for an old idea that, AFAIK, is no longer 
considered as good an idea as it used to be.  I recommend trying to make 
usually-unique identifiers like I said, and save the generic terms for 
custom `#lang`.



The hash table comes from Neovim. I can either send an RPC request (using this 
library) or run `nvim --api-info` and read from Neovim's standard output.


I'm sure you have your reasons for wanting to compile-in what Neovim 
seems to want to be dynamic info.  Such as startup performance, or the 
ability to later add annotations for semantics missing in the API 
encoding that Neovim emits.


Eventually, perhaps you'll want your Racket API interface to check at 
runtime against the Neovim process what API it supports, and perhaps 
enable/disable/change bits of your Racket API interface. You might end 
up adding annotations to your DSL, or paste multiple versions of the 
Neovim APIs into that one file, and tweak your DSL's syntax transformers 
to generate more sophisticated code.


--
You received this message because you are subscribed to the Google Groups "Racket 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Generate function defintions at compile time

2017-08-23 Thread hiphish
Thank you all for your answers, I think I got it right this time, but I
would still appreciate feedback:
https://gitlab.com/HiPhish/neovim.rkt/blob/master/nvim/api.rkt

I think what was confusing me was that I was thinking of Racket macros
like Common Lisp macros. Instead of trying to build a list that will be
the resulting S-expression I needed to build syntax objects.

> Neil Van Dyke wrote
> If you define a kind of domain-specific language (DSL) syntax
> extension in Racket for your Neovim API, your specification might then
> look like this (with the "..." filled in): 
Wouldn't making a DSL be overkill? Also, I don't have a choice in the
matter how the API data is stored, a hash table is what I receive. I do
not get the decide what the API is myself.

> BTW, consider making the `require` name be simply `neovim` or `nvim`,
> not `neovim/api` or `nvim/api`.  Or call the package `neovim-api`. 
The API is only a part of the library, there is also the "client"
(connecting to a Neovim instance) and the Racket "host" (allowing Neovim
plugins in Racket). I might later re-export the bindings from `nvim/api`
through `nvim`, I haven't decided on that yet.

> Also BTW, consider including the string "neovim" or "nvim" in the
> names of all provided identifiers of your API package, such as
> `neovim-command` instead of `command`.
Isn't this the sort of thing that should be handled by `prefix-in`? The
Common Lisp client prefixes `nvim:`
https://github.com/adolenc/cl-neovim/#neovims-api
https://github.com/adolenc/cl-neovim/blob/master/src/package.lisp#L26



> Philip McGrath wrote
> I guess my first question would be where does the hash table in
> nvim/api/specification.rkt come from, where else is it used, and is it
> necessary for the format to be what it currently is.
The hash table comes from Neovim. I can either send an RPC request (using
this library) or run `nvim --api-info` and read from Neovim's standard
output. The result is in the MessagePack format; MessagePack is similar
to JSON, except it's binary instead of text-based.
http://msgpack.org/

I wrote my own MessagePack library, and since the MessagePack standard
does not promise that keys of dictionaries need to be strings, only an
"object" I decided to unpack keys the way they are. I also use vectors
when unpacking MessagePack arrays because vectors are closer to what
arrays are than a linked list.



> Ryan Culpepper wrote
> IIUC, you are doing argument/result checking and conversion at run
> time.
No, I want to do everything at compile time. Your second code example is
what helped me to get it working, although I still don't quite
understand what `syntax-local-introduce` does and what the `#'here`
syntax object is supposed to be (I guess just some arbitrary syntax
object that's define right "here").

I'm not concerned with runtime type checks for now, I'll eventually port
the library to Typed Racket, then I'll just add the type annotations
above the function definition.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Generate function defintions at compile time

2017-08-22 Thread Ryan Culpepper

On 08/22/2017 05:29 PM, hiph...@openmailbox.org wrote:

Hello,

I am writing a Racket library which will make it possible to control the
Neovim text editor using Racket. People will be able to use Racket to
control Neovim, as well as write plugins for Neovim in Racket.
https://gitlab.com/HiPhish/neovim.rkt

So far it looks good, but I am stuck on macros. There is a hash table
which serves as a specification for which functions to generate, it is
stored in the file 'nvim/api/specification.rkt'. This table has the key
"functions" which contains a vector of more hash tables.

I need this information to generate function definitions for users to be
able to call Neovim procedures from Racket. So instead of writing
something like

   (api-call "nvim_command" '#("echo 'hello world'"))

users should be able to write

   (require nvim/api)
   (command "echo 'hello world'")

For this I need to loop over the functions vector like this:

   (define functions (hash-ref api-info "functions"))
   (for ([function (in-vector functions)])
 (define name   (hash-ref function   "name"))
 (defien params (hash-ref function "parameters"))
 `(define (,(string->symbol name) ,@params)
(api-call ,name (vector ,@params

Reality is a bit more complicated because the parameters are not a list
but a vector of vectors, but that's besides the point. The question is:
how do I do this? A regular for-loop at runtime will not work, and
wrapping this in begin-for-syntax doesn't produce actual module-level
definitions.

I tried doing it with a macro:

   (define-syntax (api->func-def stx)
 (syntax-case stx ()
   [(_ api-name api-params)
(with-syntax ([name
(datum->syntax stx
  (string->symbol
(function-name (eval (syntax->datum #'api-name)]
  [arg-list
(datum->syntax stx
  (vector->list
(vector-map string->symbol (eval (syntax->datum 
#'api-params)])
  #`(define (name #,@#'arg-list)
  (api-call api-name (vector #,@#'arg-list]))

This *seems* to generate the proper definition, although I'm not really
sure. But how can I write the loop now so that it covers all function
definitions? I don't need to re-use the macro, I only need it once, so
if there was an easier solution like my for-loop above that does it in
place it would be even better.


Using `eval` is almost always the wrong (or at least suboptimal) 
solution unless the problem is "I need to evaluate some code supplied in 
text form by someone else".


You need the names of the functions you want to define at compile time, 
because Racket requires bindings to be settled at compile time. IIUC, 
you are doing argument/result checking and conversion at run time. So, 
assuming you want to keep the information in a single hash table in a 
single module, you need to require that module once for-syntax and once 
normally.


Here's an example solution to a simplified version of the problem. I've 
simplified the specification to just the function name and its argument 
types:


  ;; file "api-spec.rkt"
  #lang racket/base
  (provide functions)

  ;; A Type is (U 'String 'Number)

  ;; functions : (Listof (List Symbol (Listof Type)))
  ;; List of function names and types of arguments.
  (define functions
'((f (String String))
  (g (Number String

And here's the module that uses that information to define adapter 
functions:


  ;; file "api.rkt"
  #lang racket/base
  (require (for-syntax racket/base))

  ;; Need api-spec at run time to create adapter
  (require "api-spec.rkt")

  ;; type->predicate : Type -> (Any -> Boolean)
  (define (type->predicate type)
(case type
  [(String) string?]
  [(Number) number?]))

  ;; make-adapter : Symbol -> Function
  (define (make-adapter function-name)
(define arg-types
  (cond [(assq function-name functions) => cadr]
[else (error 'make-adapter "unknown: ~s" function-name)]))
(define arg-preds (map type->predicate arg-types))
(define (wrapper . args)
  (for ([arg (in-list args)]
[pred (in-list arg-preds)]
[type (in-list arg-types)])
(unless (pred arg)
  (error function-name "expected ~a, got: ~e" type arg)))
  (printf "called ~s on ~v\n" function-name args))
(procedure-reduce-arity wrapper (length arg-types)))

  ;; Need api-spec at compile time for names to bind
  (require (for-syntax "api-spec.rkt"))

  (define-syntax (define-the-functions stx)
(syntax-case stx ()
  [(define-all-functions)
   (with-syntax ([(function-id ...)
  (for/list ([entry (in-list functions)])
(syntax-local-introduce
 (datum->syntax #'here (car entry])
 #'(begin (define function-id (make-adapter 'function-id)) ...
  (provide function-id 

Re: [racket-users] Generate function defintions at compile time

2017-08-22 Thread Philip McGrath
I guess my first question would be where does the hash table in
nvim/api/specification.rkt come from, where else is it used, and is it
necessary for the format to be what it currently is. For example, the first
thing that jumped out at me is that you're using strings for all the hash
keys rather than symbols, which prevents you from using a (faster) hasheq.
Also, it is strange to me that functions is a vector and not a list. But it
would probably make even more sense to use structs for many of these
things, unless it needs to be `read`-able or convertible to json or
something.

-Philip

On Tue, Aug 22, 2017 at 5:06 PM, Neil Van Dyke  wrote:

> hiph...@openmailbox.org wrote on 08/22/2017 05:29 PM:
>
>> So far it looks good, but I am stuck on macros. There is a hash table
>> which serves as a specification for which functions to generate, it is
>> stored in the file 'nvim/api/specification.rkt'. This table has the key"
>> functions" which contains a vector of more hash tables.
>>
>
> You *can* go from hashes at syntax expansion time to syntax, but, in this
> case, I think there are ways that are more idiomatic and (once you're
> comfortable with syntax extension) easier...
>
> If you define a kind of domain-specific language (DSL) syntax extension in
> Racket for your Neovim API, your specification might then look like this
> (with the "..." filled in):
>
> (define-and-provide-neovim-api
>   (version ...)
>   (error-types ...)
>   (types ...)
>   (functions ...)
>   (ui-events ...))
>
> Or:
>
> (define-and-provide-neovim-api
>   #:version ...
>   #:error-types ...
>   #:types ...)
>   #:functions ...
>   #:ui-events ...)
>
> Then you implement your `define-and-provide-neovim-api` syntax
> transformer using `syntax-case` or `syntax-parse`.  (When you're
> implementing this, it sometimes (not always) helps to type an example use
> of your syntax, then type an example of what syntax you would like that to
> expand to, and then rework those two examples into your `syntax-case` or
> `syntax-parse` form.)
>
> Or, a somewhat different way is to have separate definition forms in
> Racket for each element of the API, such as:
>
> (define neovim-foo (neovim-api-lambda ...))
> (provide neovim-foo)
>
> Or:
>
> (define-and-provide-neovim-procedure neovim-foo ...)
>
> BTW, consider making the `require` name be simply `neovim` or `nvim`, not
> `neovim/api` or `nvim/api`.  Or call the package `neovim-api`.
>
> Also BTW, consider including the string "neovim" or "nvim" in the names of
> all provided identifiers of your API package, such as `neovim-command`
> instead of `command`.  (For example, I included "roomba" in every name in "
> http://www.neilvandyke.org/racket/roomba/;.)  This is not a rule, just
> something to consider.  Personally, I would probably make it
> `neovim-command` in the API library that can be used from `#lang racket`,
> and then, someday, I have the option of making a `#lang neovim` that (among
> doing other things) provides that procedure simply as `command` rather than
> `neovim-command`.
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to racket-users+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Generate function defintions at compile time

2017-08-22 Thread Neil Van Dyke

hiph...@openmailbox.org wrote on 08/22/2017 05:29 PM:
So far it looks good, but I am stuck on macros. There is a hash table 
which serves as a specification for which functions to generate, it is 
stored in the file 'nvim/api/specification.rkt'. This table has the 
key" functions" which contains a vector of more hash tables.


You *can* go from hashes at syntax expansion time to syntax, but, in 
this case, I think there are ways that are more idiomatic and (once 
you're comfortable with syntax extension) easier...


If you define a kind of domain-specific language (DSL) syntax extension 
in Racket for your Neovim API, your specification might then look like 
this (with the "..." filled in):


(define-and-provide-neovim-api
  (version ...)
  (error-types ...)
  (types ...)
  (functions ...)
  (ui-events ...))

Or:

(define-and-provide-neovim-api
  #:version ...
  #:error-types ...
  #:types ...)
  #:functions ...
  #:ui-events ...)

Then you implement your `define-and-provide-neovim-api` syntax 
transformer using `syntax-case` or `syntax-parse`.  (When you're 
implementing this, it sometimes (not always) helps to type an example 
use of your syntax, then type an example of what syntax you would like 
that to expand to, and then rework those two examples into your 
`syntax-case` or `syntax-parse` form.)


Or, a somewhat different way is to have separate definition forms in 
Racket for each element of the API, such as:


(define neovim-foo (neovim-api-lambda ...))
(provide neovim-foo)

Or:

(define-and-provide-neovim-procedure neovim-foo ...)

BTW, consider making the `require` name be simply `neovim` or `nvim`, 
not `neovim/api` or `nvim/api`.  Or call the package `neovim-api`.


Also BTW, consider including the string "neovim" or "nvim" in the names 
of all provided identifiers of your API package, such as 
`neovim-command` instead of `command`.  (For example, I included 
"roomba" in every name in "http://www.neilvandyke.org/racket/roomba/;.)  
This is not a rule, just something to consider.  Personally, I would 
probably make it `neovim-command` in the API library that can be used 
from `#lang racket`, and then, someday, I have the option of making a 
`#lang neovim` that (among doing other things) provides that procedure 
simply as `command` rather than `neovim-command`.


--
You received this message because you are subscribed to the Google Groups "Racket 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.