
is there a Correct(TM) way of checking if a value implements an interface in a contract?

In particular I want to define a contract for a value that makes sure it implements a dictionary and imposes contracts for the keys and valies

How do I uncomment an entire region in Rhombus?

Is this PR related to what you want: https://github.com/racket/racket/pull/3670\|https://github.com/racket/racket/pull/3670

Is when
available in rhombus
?

It hasn’t been added, yet, but I imagine it should be.

Is there an efficient way to freeze a hash table (ie make it immutable)?

There’s no constant-time way to turn a mutable hash table where hash-set!
works to one that’s immutable in the sense of immutable?
and hash-set
. You could wrap a hash table with a chaperone via chaprone-hash
to reject updates, though.

Rhombus: Is there a idiomatic way of shadowing map-ref
in order for "foo"[0]
to work?

You should be able to bind #%ref
. The intent for new datatypes is that they’d implement a map interface, but that’s not fully worked out, and it doesn’t work for predefined datatypes. Meanwhile, "foo"[0]
doesn’t work out of the box, because it’s not clear that strings should be treated as arrays/maps.

Thanks, I’ll try binding #%ref
.

Rhombus: Is there a way to make a++b++c
expand to (string-append a b c)
?
This: operator (a ++ b):
~associativity: ~right
~stronger_than: && \|\|
string.append(stringify(a),stringify(b))
leads to calls of string-append
.

I thought Matthew showed an example where 1 + 2 + 3
expanded to (+ 1 2 3)

Hmm… I can’t find that now. Maybe it was a Shrubbery grouping thing vs. a parsing thing.

There is not a shorthand for defining things that expand like that. It would be possible using expr.macro
to define a ++
where its start parsing explicitly and looking for another ++
, but the API to force parsing of a tail is not really in place.


Got it. Maybe later.

FWIW here is a port of Norvig’s spelling corrector to Rhombus.
https://github.com/soegaard/rhombus-experiments/blob/main/spelling-corrector/spelling-corrector.rkt

I got used to the new syntax very quickly.

Thanks to the support for indentation in DrRacket.

Something that you could try is make a Str
annotation and hook it up to a dot provider: #lang rhombus
import:
rhombus/macro: no_prefix
racket/base:
fun make_string_refer(string :: String):
fun (index -: Integer):
base.#{string-ref}(string, index)
dot.macro '(str_dot_provider $left $dot $right):
match right
\| 'char: '(make_string_refer($left))
annotation.macro 'Str:
annotation_ct.pack_predicate('(base.#{string?}),
'(($(dot_ct.provider_key), str_dot_provider)))
val alpha :: Str: "abcdefghijklmnopqrstuvwxyz"
alpha.char(2)

I think something like this should probably be how Strings could work, except returning a Map/Ref-able interface over the string and could have dot handlers for also graphemes and maybe bytes

Here’s one in #lang racket
for comparison: https://gist.github.com/lojic/720d0b816c2e695a23b565d84a64de65

Is it, or will it be, possible in Rhombus to use one def
to define multiple things? For example, on lines 123 to 133 of @soegaard2’s example, I’m struck by how many def
’s there are.

One possible solution: write a macro

#lang rhombus
import:
rhombus/macro: no_prefix
defn.macro '(defs:
$x: $y
...):
'(:
def $x: $y
...
)
defs:
x: 1
y: 2
z: 3

Something like that is probably worth providing in the base language.

@soegaard2 do you want to give that a shot for the edits1
function?

I got "foo"[index]
to work. I also added "foo"[~to: index]
and "foo"[~from: index]
for prefixes and suffixes.


A slight change to the macro was needed.

Oooh

I’ll need to read up on annotations tomorrow.

Awesome! I like that version better.

I had assumed that the set.from_list...
line would need to be within the defs:
group, but I guess I was wrong. Does def
hoist the definition to the function scope?

Makes sense I guess - more like define
than let

Does Rhombus have something equivalent to let
?

Yes, it has let


I advocate that we should use let
everywhere possible

#lang rhombus
fun test():
let x: 1
let x: x + 1
let x: x + 1
x
test() // 3

Too many let
’s :)

Honestly, I’m fine with repeating 3 characters. That’s why I actually don’t think defs
is that necessary to be included in #lang rhombus
.
let
is especially nice for functional update. In Racket, you would either have to use define
and pick a new name:
(define x 1)
(define x* (add1 x))
(define x** (add1 x*))
or use let*
which wastes so much horizontal space:
(let* ([x 1]
[x (add1 x)]
1234567[x (add1 x)])
x)

I don’t mind the horizontal space for the bindings since you’ll come back to the left to use them: (let* ([ x 1 ]
[ x (add1 x) ]
[ x (add1 x) ])
x)

Well, when the RHSs are lambdas…

Editor support e.g. C-M-f for dealing with little blocks in Rhombus is going to be important IMO. I love being able to replace simple forms with more complex forms by copying/pasting sexprs.

I used to have to remind myself to type let*
(coming from SML, where let
is let*
). Then I got used to internal define, but I still think in lets.

I love the self-containedness of (let ...)

I don’t see any nested let
examples on the page linked to above, but I assume that’s possible, right?

What do you mean by nested let
? What I wrote above is nested let

Re self-containedness: you can use begin:
to create a scope.

E.g.,
begin:
let x: 1
x
x
is not visible outside the begin
block.

Now I’m confused. The Rhombus let
above doesn’t have each let
indented, so I didn’t think it was nested.

So, the Rhombus: fun test():
let x: 1
let x: x + 1
let x: x + 1
x
is equivalent to: (define (test)
(let ([ x 1 ])
(let ([ x (add1 x) ])
(let ([ x (add1 x) ])
x))))

Hmm….

Yep

IIRC, OCaml has a similar feature

Except if you have def
inbetween.
#lang rhombus
fun test():
fun foo(): a
let x: 1
let x: x + 1
def a: 42
let x: x + 1
foo()
test()
In Rhombus the a is visible from the body of foo
.

Yes, let val x = 1 in
let val x = x + 1 in
let val x = x + 1 in
x end end end
Though I would write let
val x = 1
val x = x + 1
val x = x + 1
in
x
end
or even let
val x = 1
val x' = x + 1
val x'' = x' + 1
in
x''
end

Oof, I’m not sure how I feel about that last example. Seems too much like magic to me

Makes sense to me. The scope of identifiers declared with def
is the entire function body.

I think I’m too used to let creating scope, so the def looks hoisted way out of the let.

Agreed - that def
above makes me very uncomfortable :)

I think of def
as equivalent to internal define in Racket. So if you just stay away from let
, everything works as usual :slightly_smiling_face:

Well, val
.
IMO, def
is bad. Here’s an example that Matthew alludes to in the talk:
struct posn(x, y)
def pin: posn(3, 4)
def posn(pin_x, pin_y): pin // function def or pattern matching?
def posn2(pin_x, pin_y): pin_x // function def or pattern matching?
(copied from https://github.com/racket/rhombus-brainstorming/pull/163#issuecomment-947677474)
def posn
is a pattern matching. def posn2
is a function definition. But by only looking at the text alone, you have no idea which is which.

If the convention is to use upper case: class Posn(x,y)
then def Posn(x,y): ...
is easier to spot as pattern matching.

That also requires a convention/rule that function names won’t start with an upper case letter.
And IMO it’s still confusing even with the convention, but perhaps it’s a matter of getting used to it.
What about unicode struct name/function name (that doesn’t necessarily have a notion of “uppercase”/“lowercase”)?

:shrug::dizzy_face:

Does the same emoji in a different color count as the same identifier?

I hope not lol

I know we’re still working through the communication strategy, but if you were to create two categories of “more synchronous” and “less synchronous”, would it be fair to say the former contains { Slack, IRC, Discord }, and the latter contains { Discourse, Mailing Lists } ? And if so, how do folks feel about just picking one from each set? :) I think I would personally favor consolidating one from each set, even if the choice is not my personal preference, just to avoid fragmentation.

I suppose IRC is a separate thing, so for me, I guess it mainly comes down to choosing between Slack & Discord, and between Discourse & Mailing Lists. The latter is a little easier for me, I think Discourse has more advantages than Mailing Lists, and I agree about the precedence w/ other language communities. I probably dislike Slack & Discord roughly the same, so I would just go where critical mass is.

discord has the added dislikability of banning users for using alternative clients while also having invasive data collection in their own client.

I don’t know how much of a positive it may be, but a lot of people these days end up using Slack at their day jobs, whereas I’m not sure that Discord doesn’t have a narrower ‘market’ (I could be wrong, I’m not really a Discord user)

I think discord has been getting a lot more mindshare in larger community groups because they don’t have the message limit on free plans

Between the “more” and “less” synchronous, I’m probably more concerned about the latter, and the ability to have an unlimited archive of searchable information. So, if Discourse allows for that, it’s fine with me.

I really don’t care about the message limit for free plans, because Slack’s search is not great so nobody uses it anyway. I’d argue that Slack/discourse/irc/whatever should be treated more like a social space. If someone showed up to a social gathering with a bunch of tape recorders and insisted everyone spoke into them at all times because every conversation must be recorded, I think most people’s reaction would be, “No they don’t.”

Re: forum vs email, personally I’d vote forum; I prefer not to participate in email lists because then I end up with a lot of email to delete.

We had a hallway discussion about some of this yesterday. One concern was the searchability/archive question. @spdegabrielle pointed out some of the things worth searching for should probably be in the Github Wiki. @joel pointed out some other projects where it is easy to move data from ephemeral chat type systems into like a mediawiki.

yeah, I’ve even seen a few groups that archive their slack automatically, so there’s a history/search index available separately… that does brings up the question of do people expect everything they say in chat to be archived on the web forever, though

My personal take is that Team Racket (TM) can decide whatever they want is “official”, but the community (and enthusiasts outside of the discord/slack/email “core” community) are going to have enclaves where-ever they please.
I do think when Team Racket does bless a community there are members of the community (or even Team Racket) that can be trusted to uphold our shared community standards.

@ben.knoble does run a slack archive, although I haven’t looked at it myself.

> that does brings up the question of do people expect everything they say in chat to be archived on the web forever, though I have a pet hypothesis that social anxiety around the knowledge that everything you say will go down in your permanent record is a factor in why flamewars were more common on public web forums than they seem to be in Slacks.

slack has always seemed pretty on top of filtering out known bad actors, too… so bans of troublemakers actually have a reasonable chance of some effectiveness vs people just immediately popping back on w/ a new account.

I guess that’s peep me. The archive is opt-out, so we can (and do) exclude messages from folks that prefer to abstain from the archive. We also exclude certain channels by default because they just don’t have useful info. There have been suggestions about collecting the useful info out of the archive; it needs to be done automatically though, because the archive is kind of huge. The archive is moderately searchable using site: queries, though I haven’t been able to make that work myself; implementing search proper is a todo that I don’t have expertise in.

In my opinion, fragmentation is less of an issue for socializing than for a knowledgebase. If some people want to chat on Discord, and others on Slack/IRC/etc., why not? But it seems handy to me to have one primary platform for Q&A, design brainstorming, etc. where the network effect for searching is a plus.

I agree with that^

Q&A is kind of borderline… a good sync community can really hash out a question quickly compared to back and forth on a forum

The example I was talking about in the hallway discussion was the IndieWeb community. They have an ephemeral chat space and they have a wiki, and they have a chat bot that facilitates both the collection of info into the knowledge base and referencing it out. I’ve never seen a better model for this kind of community.

I agree, and despite my desire to have a nice knowledgebase of Racket Q&A, I’m as guilty as the next person of firing off a question on Slack because I figure I’ll get a quick response :)


One of the things SO tried to do was avoid that kind of fragmentation. I think they ended up with it anyway, parts accidentally and parts on purpose (it’s just so dang hard to categorize a priori, and it always looks wrong from certain points of view post hoc). OTOH vi.stackexchange being small and focused does pretty well. The reason I value the archive is because I think there are gems in there waiting to be found, and I would like to use that to reduce knowledge fragmentation/ask the right person to get an answer.

The Discourse has good support for q&a

If it is of any value I compiled a spreadsheet of how other pl communities communicate https://docs.google.com/spreadsheets/d/1WxnA2NYmj33w7TVA4QWwMQUaqh3lQzhE8MN6QSheyCQ/edit?usp=sharing\|https://docs.google.com/spreadsheets/d/1WxnA2NYmj33w7TVA4QWwMQUaqh3lQzhE8MN6QSheyCQ/edit?usp=sharing

poor gitter gets no love :upside_down_face:

@jujuzi0202 has joined the channel

My view is that the split @badkins points to is real, and I’d be happy to standardize on Discourse provided that it works for people.

I also prefer slack over discord but the difference in activity level is real.

Finally, it’s worth noting that the real replacement for mailing lists is GitHub and that isn’t going to change no matter what we choose.

@yyqqqaq has joined the channel