@cdep.illabout_slack This is already a long thread, but, wrt to seeing source: I’ve found this to be less useful in Racket than in say Emacs or Clojure. I think it’s because, when the source is Racket itself, the source is not as simple as I might have expected/wanted/hope.
There might be layers of re-providing, re-naming, DRY-ing, definer-defining, and so on.
So, e.g., “Cool, I can see the definition of lambda
! Oh, it’s really new-lambda
. And wow, keyword arguments really complicate matters, huh. And gee, it needs to be written at such a low level, it’s very verbose Scheme as opposed to what you might consider ‘modern Rackety’. Um…. what was I thinking before I got here….”
So I’m not saying you’re wrong to want to see this. Just pointing out it might not always be what you want to see. :slightly_smiling_face:
By the way, my (maybe wrong) guess is that much of that complexity is due to Racket being decades old, and, good about trying to maintain compatibility.
There have been events like renaming it from “PLT Scheme” to “Racket”, changing the default file extensions. And keeping everything working for old and new.
I don’t think that’s true in most cases — new-lambda
isn’t complicated (as you point out) because of compatibility, but because of Racket’s approach of implementing higher layers using lower layers
The expander, for example, is easier to read in some ways, because it’s bootstrapped instead of written in a lower-level language.
Oh, yeah, I wasn’t trying to say there was one main explanation for it — much less that I felt the complexity was unwarranted or managed badly.
There are definitely places where your explanation is the correct one
I was careful to use the weasel phrase “much of”. :slightly_smiling_face:
It’s interesting to see the style difference in various code. And yes, 10 year old code looks different.
I think one of the biggest reasons is pervasive error handling
Recently I looked at some code I wrote pre for
. Quite a difference.
And let
is everywhere, no define
Racket provides many well-thought-out abstractions and I can normally work at a nice high level appropriate for what I want to do. I might think it’s like a duck, and I’ll see a pair of little feet paddling under the water. But when I look, it’s more like an iceberg — there’s a lot more there than I expected! <— Maybe better way of putting it.
yes, I think that’s true. and the way the layers work out mean that more of it are visible when you “view source” than in Haskell or Clojure
@sorawee > And let
is everywhere, no define
let
! You were lucky! My family had to use (let-values (_) (lambda _))
in a shoebox in the middle of the road!
let-values!
You were lucky to use let-values!
. In my family we used to live with without values
, all twenty-six of us. No case sensitive symbols and half of the binding constructors were missing. We had to simulate pairs
using lambda
to get by.
is there a way to convert back into the struct from a struct->list
? like a list->struct
, i dont want to rely on the external packages. I presume i can just splice in the struct-list
, like (struct-id (struct->list)
to convert back? struct-id being parameterizable?
Can’t you use (apply struct-id args)
?
ooo, never thought of that, thanks it works!
I’m slow on the uptake so I’m just beginning to wrap my head around macros. I was following <https://media.ccc.de/v/rc3–257534-all_programming_language_suck_just_build_your_own_language_oriented_programming_with_racket|this video> by Mike Sperber. The <https://github.com/mikesperber/rc3|code is on github>. I’m trying to add to it to make it run the basic-demo-syntax.rkt
code immediately after parsing it. In other words it currently works by first running the file then typing (line-10)
into the interactions window of DrRacket. Instead I’d like it to run after I hit Run (or Command-R). I know that what needs to happen is for lines 10 and 11 in basic-reader.rkt
to go from (basic
,@(parse-program src in)))))
to (basic
,@(parse-program src in))
(line-10))))
but, of course, I don’t want to assume that the first line is always line 10. My current solution is to (1) move the parsing into let
as: (let ([whole-program (parse-program src in)])
then (2) change the lines above into: (basic
,@whole-program)
#`(#,(make-line-name #`running-program ,(caar whole-program)))))))
but when I try to run the demo I get the error “make-line-name: unbound identifier in: make-line-name” even when providing make-line-name
from basic.rkt
using (for-syntax make-line-name)
. I think I have a second problem too where ,(caar whole-program)
won’t get translated into 10
because of the complexity (at least to me) of datum->syntax
and #
(#,(` etc. Any help would be very much appreciated! I’d rather not have the solution but a hint or two in the right direction. Where should I go or what should I read?
is there a way to get the struct-id from the instance and construct it?
(define (canonacalize-struct struct-id instance)
(define turn-hashes-to-lists (lambda (item)
(cond [(hash? item) (hash->list item)]
[else item])))
(apply struct-id (map turn-hashes-to-lists (struct->list instance))))
I currently have to pass in the struct-id as a parameter
@javier123mendoza has joined the channel
Provided that your struct is #:transparent
, this should work:
(struct foo (bar baz) #:transparent)
(define-values (struct-type ignore) (struct-info (foo 1 2)))
(define ctor (struct-type-make-constructor struct-type))
(ctor 3 4)
:kissing_heart: thanks again
Hi @joshua.e.cottrell
You plan works - however, I think it will be simpler to modify the basic
macro. The idea is often to make the reader as simple as possible.
The basic
form receives the entire program and starts like this:
(define-syntax (basic form)
(syntax-parse form
((basic (line-number:integer command:expr) ...)
<more here>
We see that we can extract the first line number by doing this: (define first-line-number (first (syntax->list #'(line-number ...))))
At the end of the program that basic
generates, you will need to insert a call to the function of the first line.
You can either look at how the translate
command produces such a call: #(#,(make-line-name context #`line-number))
Or perhaps even try something like this (translate #`basic (goto #,line-number) #f)
which should produce the same call, but might be simpler to read.
Great stuff @soegaard2! Thanks for the advice on where to add it. I decided to use the goto
method you described. I added the define before the #
(beginand interestingly couldn't use
first. I guess it's not bound for syntax. I used
carinstead:
(define first-line-number (car (syntax->list #(line-number ...))))
then added #,(translate-command #
basic #(goto #,first-line-number) #f)
as the last part of the #
(begin` . It seems to be working well now. Thanks again for your help!
You are a right about first
. It’s not part of racket/base
, so an (require (for-syntax racket/list))
is needed.
@curiouslearn has joined the channel