
@sarna.dev has joined the channel

hey, is there any benefit that parameters bring to the cmdline module? for me they seem like unnecessary clunkiness

Parameters as in “command line arguments” or as standard Racket parameters?


Wait a minute, did we pay Slack for full history?

Huh - I too see very old messages when I search.

thanks @sorawee


Oh lol

I think this is a good opportunity to achieve everything

@soegaard2 parameters as standard Racket parameters. all the other CLI libraries I’ve used were more.. functional? and only in Racket you modify global state from within the arg parser, which I find weird

I’m used to passing functions to the parser, that take CLI args as (function) arguments

@sarna.dev The user of cmdline
determines what happens in the handlers-exprs
, so you can do use simple globals, parameters or something else.

I think it’s true that the cmdline library forces you to use mutation. A more functional variant would definitely be better, but we probably can’t change the existing one since it would break backward compatibility.

Many Racket libraries use parameters to represent global variables. The form parameterize
makes it easy to temporarily set the globals to something different (and parameterize
also works in programs with multiple threads).

@laurent.orseau will now sell his library :slightly_smiling_face:

:sweat_smile: See also the global
package

I find it makes dealing with the command line much simpler, but it has its limitations.

@laurent.orseau it doesn’t support subcommands >:(

It probably won’t anytime soon either

(the standard cmdline doesn’t either)

The standard cmdline doesn’t, but it’s possible to hack it to support subcommand. That’s the approach that raco pkg
uses.

Would be nice to have a package for this though

Can I get a translation?

where’s the source code for raco? I can’t find it


Oh wait, it looks like I misunderstood. They actually kinda reimplement racket/cmdline
?

it looks complicated as hell though lol

(for my beginner eyes)

Yes, definitely not for public use


Do we need any slack email adresses?

This one claims to support “svn style command lines”, but it’s in the old package system: https://planet.racket-lang.org/display.ss?package=functional-command.plt&owner=cobbe

@sarna.dev I take it back. I think I was right. It uses racket/cmdline
internally


which is used in the first file I linked above

One for #general, and one for an #announce channel - it would make cross posting easier.

thanks for the pointers! I want to implement something like https://github.com/l3nz/cli-matic\|https://github.com/l3nz/cli-matic in Racket but I’m a very confused beginner >.> no idea what’s the “Racket style” and stuff, kinda afraid to make mistakes

You should give it a try! I’m sure people here can help you with the “Racket style” stuff

And if you like, you could run resyntax
over your code to get some racket style suggestions :p

I wonder what it would be like to try to use (abuse?) syntax-parse for command-line argument parsing.

now you’re thinking with ~portals~ macros

Racket has quite a few “pattern matchers”. On the one hand, this can be a downside when learning, and, maybe some of the variety is historical accident? On the other hand, maybe the variety is useful specialization for various tasks? I don’t know to what extent it would be desirable, or even possible, to “unify” most of them? Or maybe it’s “just” a job for a user’s guide and/or cheat sheet format, to point out the various systems and give an overview compare/contrast.

[I’m not sure it’s some kind of huge problem. Partly just make sure people know some of the choices. Leverage common concepts they’ve already learned. Avoid getting bitten by details like ..+
vs. ...+
.]

@sarna.dev definitely do try. That’s the one way to make progress. We can help to the extent of our available time and knowledge

@greg maybe the easy way is to rewrite match based on syntax-parse?

Would be an interesting package :)

I think it just means “sweet, you’re all done” with some food on the side

If I execute a file struct-test.rkt
, #lang racket/base
(struct foo
(x y z)
; Shouldn't this prevent the creation of a `foo` name/binding?
#:constructor-name foo-struct)
; Results in
; struct-test.rkt:12:8: module: identifier already defined
; at: foo
; in: (define-values (foo) 1)
(define foo 1)
with racket
, I get an error message as shown in the code. I had expected that if I rename the constructor with #:constructor-name
, there wouldn’t be a need to create a name/binding foo
from the struct, so I could use the foo
name for the define
below.
Is the above error expected behavior and if yes, why?

When I saw that Racket uses Slack I was a bit concerned by the message storage limit. I think we have great “preserve-worthy” discussions here.
What are the plans when the trial period runs out? Just live with it? Create a website/subdomain with a searchable archive (if the data can be exported with the means provided by Slack)? Move to a different messaging platform? Something else?

if you replace your last line with foo
, you get the error:

foo: bad syntax;
identifier for static struct-type information cannot be used as an expression in: foo

I suppose this is the match expander?

Add the following property: #:name foooo
and the error goes away

@laurent.orseau This seems to help, thanks! Unless someone can come up with a good excuse :wink: for the current behavior, I’ll try to find a ticket or enter one.

I now use unused-<name after
struct>
for the name.

I don’t think it’s a bug though, i didn’t look too much into what this #:name
does. Understanding this would probably explain why you didn’t obtain the behaviour you expected. Probably the docs can be improved though.

My wishlist features:
- Autogenerate shell completion
- Good error message (do you mean “x”? — perhaps based on edit distance)
- Macro extensible

@samth should be able to answer that, but my impression is that we have been living with it (prior the standard trial enrollment)

I think it would be great if we can:
- achieve everything until now
- once the free trial is expired, achieve last month’s content, every month

Yes, the plan is to live with it, unless someone wants to take on the project of providing an archive

I’m happy to help with that but I’m not going to take it on myself

The name there is what’s used in match, for creating substructures, etc

I might be interested—depends on what the archive format is, but would a github repo that deploys (via pages) or something work? I can’t be responsible for creating the archive each month, but I can take the data (transform as necessary) and put together a barebones set of static pages. Search-ability is not my forte, though.

I can download things and send it to you

It’s working on creating the export. I’ll message you when it’s available.

^what samth said; the name contains syntax information that is used to cooperate with other components of racket. Cf. https://drive.google.com/file/d/1VHhJGhh44Sq9YCs30GkpMT9hCnCeTmD-/view\|https://drive.google.com/file/d/1VHhJGhh44Sq9YCs30GkpMT9hCnCeTmD-/view

I think it’s an american colloquialism, but its not from the region I’m from.

Why ‘macro’ extensible though?

Instead of #:name some-bogus-name
, you can also write #:omit-define-syntaxes
.

@mikhailk897 has joined the channel

@philip.mcgrath Thank you, I’ll try it. I now read the paragraph on #:omit-define-syntaxes
and must admit I didn’t understand whether I only lose access to the name or if it has any other disadvantages that I’ll notice. (I’m not complaining; I don’t expect you to explain all the background in detail. :slightly_smiling_face: )

Yes, it’s confusing! (I still don’t understand when or why one might want #:omit-define-values
.) AFAIK, if you don’t want the static information bound to the name, there’s no disadvantage: just, you might want to bind it to some internal name if you’re doing something more involved (e.g. using it to implement a match expander).

Here’s an outline of what I’m doing: http://pasterack.org/pastes/93106 .
The gist is that I’m creating the actual struct
instances with a helper function make-group-params
and I want to call the hash group-params
, which is/was the original name from the struct
type creation.
I still want the struct accessor functions like group-params-unset-value-title
to be able to access the struct objects returned by make-group-params
.

Fun diff I generated with resyntax
today. Old code: (define read-token
(case-lambda
[()
(read-token #f)]
[(count-lines?)
(let* ([pos (if count-lines?
(let-values
([(line col pos) (port-next-location (current-input-port))])
(list line col pos))
(file-position (current-input-port)))]
[m (regexp-match non-delimiter*-regexp (current-input-port))])
(and m
(match m
[(token . _)
(list (if (token-case-sensitive)
token
(bytes-downcase token))
pos)])))]))
New code: (define (read-token [count-lines? #f])
(define pos
(if count-lines?
(call-with-values (λ () (port-next-location (current-input-port))) list)
(file-position (current-input-port))))
(define m (regexp-match non-delimiter*-regexp (current-input-port)))
(and m
(match m
[(token . _)
(list (if (token-case-sensitive)
token
(bytes-downcase token))
pos)])))

That’s pretty neat.

I am attempting to get flomat
running on Windows. I have built libopenblas.dll
with msys2/mingw64 and now have a libopenblas.dll
. I copied the dll to “C:\Program Files\Racket\lib” but Racket doesn’t find it anyway. Any ideas?


There’s a logger for FFI search information

Do I need to do more than choose “Show log” in the “View” menu of DrRacket?

You might need to change the log level

If you just show every thing at the info level I’m sure it will be there

Found this:

So the file exists, but isn’t loaded.

Might be 32 vs 64 bit, or any of many other things

I think, I’ll try to modify the “OS library search path” instead.

I think, everything is 64 bit.

The DLL itself might have dependencies of its own (other DLLs), and if these are not found, the error is misleading, reporting that the original DLL cannot be found.
I would suggest using a tool such as “depends” to find out if all the dependencies of “libopenblas.dll” are actually found.

this error is not Racket specific. the LoadLibrary
call returns “not found”, without giving any indication of what was not found…

That’s a good point. I get:

The /mingw54/ paths look wrong

I think Racket and ldd
use different search paths — I would suggest downloading and using delends.exe

Do you think, I can solve the problem by not moving the dll, and instead add the original location C:\msys64\mingw64\bin to some Windows search path ?


yes, that one

you will need the 32 or 64 bit version depending on the actuall application, not OS. So if you use 32 bit Racket, you need the 32 bit version

delends.exe showed where the problem were. First attempt at fixing the problem: not move the dll at all (let’s see if it works).

That seemed to work.

I don’t get why the OpenBlas project doesn’t provide binaries for Windows though. Seems odd to get everyone to compile them (and without any instructions).

Another fun resyntax
diff. Old code: (let ([key (list lexicon-file block-size block-pos)])
(hash-ref cache key
(lambda ()
(let ([mlb (read-lexicon-block lexicon-file block-size block-pos)])
(hash-set! cache key mlb)
mlb))))
New code: (define key (list lexicon-file block-size block-pos))
(hash-ref! cache key (λ () (read-lexicon-block lexicon-file block-size block-pos)))

@notjack can you generate hash-update too?

@samth Not yet, the implementation is trickier. Consider this code: (hash-set! h k (+ (hash-ref h k) 5))
I need a way to check that the new value contains the expression (hash-ref h k)
somewhere inside it, but I don’t care where

syntax parse doesn’t have a built-in way to do that, I’d need to build a pattern expander or something similarly clever

That’s pretty nice. From little-helper ?

@soegaard2 yup, hope you don’t mind me using it as a test corpus :sweat_smile:

Not at all. It’s kind of ideal, since the code is to the old side.

I am kind of surprised, it still runs :slightly_smiling_face:

no guarantees it still runs, resyntax only checks that it still compiles :p

Not sure if it will be worth it, but
(and m (match m ...))
could be rewritten to:
(match m [#f #f] ...)
to reduce the drift

You can use recursive syntax class to find a pattern, though that doesn’t look like a good idea. What if it’s in quote
?

Is there a way to defeat the separate compilation guarantee for module+
? By that, I mean, I want:
#lang racket
(module defn racket
(provide mac)
(define-for-syntax counter 0)
(define-syntax (mac stx)
(set! counter (add1 counter))
(println counter)
#'(void)))
(require 'defn)
(mac)
(module+ test
(mac))
to output 1 and then 2.

The fully correct solution would probably involve local expansion of some kind, but I’m fine with only partial correctness if the error cases are pathological

Yeah I feel similarly about that one. It seems like weird code either way, so I’m not sure it’s worth recommending.

Obviously, define-for-syntax
is a wrong thing to use here, but what could I use instead?
This almost works:
#lang racket
(module defn racket
(provide mac)
(define-syntax (mac stx)
(define counter (datum->syntax stx 'counter))
(define val
(cond
[(syntax-local-value counter (λ () #f)) => values]
[else 0]))
(println (add1 val))
#`(define-syntax #,counter #,(add1 val))))
(require 'defn)
(mac)
(module+ test
(mac))
but it causes with another problem: we need to supply the right lexical context (which is very tedious), or else it will fail.
#lang racket
(module defn racket
(provide mac)
(define-syntax (mac stx)
(define counter (datum->syntax stx 'counter))
(define val
(cond
[(syntax-local-value counter (λ () #f)) => values]
[else 0]))
(println (add1 val))
#`(define-syntax #,counter #,(add1 val))))
(define-syntax (mac2 stx)
#'(mac))
(require 'defn)
(mac2)
(module+ test
(mac2))

Do you need (mac2) (mac2)
to increment the counter twice even if they’re in the same module? If you don’t, then going ahead and passing the lexical information through is probably a good approach, even if it seems tedious.
If you do, then it seems like a set!
approach would be more viable than using define
each time. But I think you’re right about that being hard to carry over to submodules.
In that case, I think a good option is to kinda toss out the expectation that Racket’s existing module-level declarations are set up for this. Perhaps you can define your own module+
variant that reads the state of the counter in the outer module and creates a definition that initializes it to that value in the submodule.
At the extreme end (if none of that is good enough), perhaps you can break the separate compilation guarantee decisively by using the logger, having the defn
module set up a log listener that acts as a server for the state of the counter, but doing some kind of handshake to ensure you only set up that listener if the same listener hasn’t already been set up.

Yep, I expect mac2
to increment the counter twice.

This is an annoying limitation of https://docs.racket-lang.org/mixfix/. I want to see if it’s possible to workaround the issue.

Is this workaround usable? #lang racket
(module defn racket
(provide mac get-mac)
(define-for-syntax counter 0)
(define-for-syntax (inc!)
(set! counter (add1 counter)))
(define-syntax (mac stx)
#'(begin-for-syntax
(inc!)))
(define-syntax (get-mac stx)
#`'#,counter))
(require 'defn)
(mac)
(get-mac)
(module+ test
(mac)
(get-mac)
)

Not quite, but very close!
The problem with that approach is that mac
could not be invoked in an internal-definition context. But I think I can make it expand differently based on syntax-local-context
. Let’s see if it will work. Thanks!

Why does it work though?