IRC channel logs


back to list of logs

<daviid>taylanub: could you check if it's ok after ,use (oop goops) ? or did you maybe?
<davexunit>ACTION goes afk
<daviid>maybe another name, not set!, don't know, but anyway, it has to work with, cooperate with goops, even though it is sfri, since goops is an will remain an essential part of guile
<taylanub>certainly. I'll see how it inter-operates.
<taylanub>daviid: does GOOPS' set! ever take more than two operands, or is (set! (accessor ...) value) the only addition? if the latter, that's the same as SRFI-17, so it's fine.
<daviid>taylanub: it always takes 2 args, (set! (accessor ...) value)
<daviid>but my concern is the 'side' effect, wether a user import your srfi, goops, on in the other order ...
<daviid>taylanub: it would be good if you could play with this a little, make a couple of classes, inheritance, sigle, multiple, instances ... no big deal, and make sure your work is compatible... my 2c
<daviid>taylanub: in the spec, the use of the term 'object' is unfortunate, imo
<daviid>item maybe? i'm not a native speaker, but object(s) and instance(s) should be avoided I think
<dsmith>sneek, seen dsmith?
<sneek>dsmith was here Aug 16 at 12:41 am UTC, saying: sneek, seen dsmith?.
<dsmith>sneek, seen dsmith?
<sneek>dsmith was here Aug 16 at 12:42 am UTC, saying: sneek, seen dsmith?.
<dsmith>The date command and sneeks time is an hour different.
<dsmith>Ah well.
<taylanub>daviid: the standards use the terms "value" and "object" (as synonyms) to refer to arbitrary values/objects. E.g. in section '1.1 Semantics' of R5 and 7RS: "Types are associated with values (also called objects) ..." and '1.1 Basic types' of R6RS: "Scheme programs manipulate /objects/, which are also referred to as /values/."
<taylanub>ACTION can't find out where Guile's set! that works with accessors is defined.
<mark_weaver>set! is a core construct in psyntax.scm
<mark_weaver>our version of psyntax has support for generic "procedures with setters", see section 6.9.8 of the guile manual.
<mark_weaver>search for "(global-extend 'core 'set!" in psyntax.scm
<taylanub>I see. it seems I just need to fall back to ((@ (guile) set!) <place> <expression>) in my extended set! definition
<mark_weaver>the 'syntax-case' in there has two non-error cases, the first is normal 'set!' and the second is for procedures with settings
<mark_weaver>taylanub: yes
<taylanub>thanks :)
<mark_weaver>and that decision needs to be made at expansion time
<mark_weaver>(whether to fall back)
<mark_weaver>but I guess in your case you can do that because it depends only on the number of operands, right? you handle the 3-argument cases, and core guile handles the 2-argument case?
<mark_weaver>I confess it's not clear to me what is gained from your (set! object field value) over the more established (set! (field object) value)
<mark_weaver>s/over/syntax, over/
<taylanub>the intro of the rationale explains: In some types of code-bases, accessing and modifying fields of certain collection objects (such as vectors, hashtables, or records) are ubiquitous operations. Standard Scheme APIs contain verbose procedure names specialized for each data type, which may become very tedious to type, and clutter the code.
<mark_weaver>the latter seems more natural to me, because it reflects the idea that (field object) is sort of an l-value.
<mark_weaver>that's an argument in favor of your syntax over (field-set! object value)
<mark_weaver>but I'm wondering what is the advantage of your syntax over (set! (field object) value)
<taylanub>in the (set! (getter object) value) variant, the 'getter' is still the verbose getter (sometimes with an extra argument for the actual field, like the vector index, hashtable key, etc.), whereas in my case the getter is omitted entirely and only a field identifier provided (index, key, etc.)
<taylanub>i.e. (set! (hashtable-ref table key) value) is not shorter than (hashtable-set! table key value), but (set! table key value) is
<mark_weaver>okay, but how about (set! (ref table key) value) ?
<mark_weaver>in other words, maybe you should focus just on a generic 'ref', and reuse the more established (set! <place> value) concept
<mark_weaver>I suppose your way saves one more word, by getting rid of the 'ref'.
<mark_weaver>but it does so at the cost of losing this concept of a l-value <place>
<mark_weaver>with the <place> approach, you can think of (ref table key) as being a place, used for both querying and setting.
<mark_weaver>and then you can define a macro that expands to (ref table key), and that same macro can be used for both referencing and setting.
<mark_weaver>you can't do that with your approach
<mark_weaver>a macro that expands to (ref table key) cannot be used to create (set! table key value)
<mark_weaver>but it can be used to create (set! <place> value), because it can be used in <place>
<taylanub>(set! (ref ...) value) is possible with the SRFI-17 integration of the library, but wouldn't you say the ref is misplaced there, intuitively? in fact, (set! (vector-ref v i) x) already seems strange. I think the lvalue concept already falls apart when we use a name like "foo-ref" to refer to a place. it says "reference" (a verb), not "field" or so
<mark_weaver>well, okay, agreed. but I think that just speaks against the particular name 'ref'.
<mark_weaver>if you chose a different symbol, then it could apply more naturally.
<mark_weaver>if you make a macro that creates a 'place' that can be used by set!, then it is no longer only for ref'ing but more generally for accessing.
<mark_weaver>perhaps some name made of non-letter symbols would be more natural, and shorter.
<mark_weaver>actually, gauche has something like this.
<mark_weaver>let me try to find it.
<taylanub>combining SRFI-17 and 105, renaming set! to := and ref to $bracket-apply$, the following is possible: {object[field] := value}
<taylanub>but IMO such syntax doesn't fit well into typical Scheme code (i.e. if it doesn't already use SRFI-105 heavily)
<mark_weaver>gauche calls it ~
<mark_weaver>I would encourage you to read it
<taylanub>huh, didn't even know they already have 'ref'. I got the ider from Jorgen Schäfer, dunno if coincidence or if he got it from there. will read.
<mark_weaver>shiro is really smart, and puts a lot of thought into his APIs, and makes sure they are well tested by real experience before committing to them
<mark_weaver>anyway, it's very late here, I must sleep now
<mark_weaver>happy hacking!
<taylanub>good night :)
<mark_weaver>actually, one more note before I leave...
<mark_weaver>looking at the psyntax code, it appears that <place> is not actually macro expanded before its car is assumed to be a procedure-with-setter
<mark_weaver>well, to be more clear: I think it might not be macro expanded at all
<mark_weaver>(set! (head tail ...) value) is essentially expanded into ((setter head) tail ... value)
<mark_weaver>but the (head tail ...) subform is not actually expanded, so if 'head' is a macro, it won't work.
<mark_weaver>however, we could, and probably should, handle the case where 'head' is a macro.
<mark_weaver>well, it would be a bit tricky
<mark_weaver>but it could be done
<mark_weaver>I think so anyway.
<mark_weaver>well, I'll have to pick this up another time. good night!
<mark_weaver>ACTION --> zzz
***michel_mno_afk is now known as michel_mno
<paroneayea>hello #guile!
<artyom-poptsov>Hello paroneayea
<paroneayea>hi artyom-poptsov
<paroneayea>working my way through again!
<paroneayea>making much more sense this go around.
<paroneayea>mark_weaver: btw, do you think davexunit's (ice-9 json) stuff is more likely to go in guile-2.0.x or guile-2.2.x?
<taylanub>mark_weaver: I decided to adopt Gauche's ~. a remaining question is whether it would make sense to support (set! obj field val) as a special case / simpler version of (set! (~ obj field) val), since it's likely to be the most common use. I have a slight preference for it, but Shiro Kawai and John Cowan don't like it. I'll let the collective opinion decide.
<paroneayea>I am debating what to do with my own code for the moment; maybe I should include a copy of the file in activitystuff in a "contrib" directory for now
***michel_mno is now known as michel_mno_afk
<mark_weaver>taylanub: I think that (set! (~ obj field) val) is better
<mark_weaver>I don't like the (set! obj field val) syntax
<mark_weaver>fwiw :)
<mark_weaver>btw, another advantage of the (set! (~ obj field) val) syntax is that it generalizes nicely to properties of multiple objects, not just single objects.
<mark_weaver>well, sorry, that's not quite coherent, since ~ itself is limited to properties of single objects.
<mark_weaver>what I mean is that (set! <place> value) can generalize to cases where <place> is a property of multiple objects.
<sbidin`>Hi. If I have a reference to a #<procedure...>, can I get its name?
<mark_weaver>well, there's 'procedure-name', but it might not work in all cases. if you're writing code that depends on this, that's probably a bad idea.
<mark_weaver>might I ask why you want this?
<sbidin`>Yes, it doesn't work in my case. I'm assuming it's not a named function.
<sbidin`>As to why I'm doing it, I'm interested in what exactly guix's %desktop-services contains, and I thought it would be fun to do it without visiting the actual definition in the source.
<mark_weaver>ah, okay
<mark_weaver>well, for example, the first item in %desktop-services is the result of evaluating (slim-service)
<mark_weaver>it is *not* the procedure 'slim-service'. rather, it is the result of calling 'slim-service'.
<mark_weaver>so the information that you want is already lost.
<mark_weaver>or at least not in a nice form.
<mark_weaver>the result is a "monadic value"
<sbidin`>Ah, I understand. I think I'm too used to pervasive laziness and I just assumed it wasn't evaluated yet.
<mark_weaver>so, these "monadic values" are, at bottom, procedures that accept a state and return a value and a new state.
<mark_weaver>there is an element of laziness here: the procedures you see, which actually build the store items, have not yet been executed.
<mark_weaver>however, the procedure 'slim-service' that creates the procedures you see, have been evaluated.
<mark_weaver>*procedures such as 'slim-service'
***DerGuteM1 is now known as DerGuteMoritz
<davexunit>paroneayea: my patch targets stable-2.0, I should have said so in my email.
<davexunit>it does not break any existing interfaces and does not depend on any features only available in the master branch.
<davexunit>in fact, I implemented certain things differently than I would have if I were targeting master.
<davexunit>such as creating lists via tail call recursion and reversing the result rather than just using a regular recursive process.
<paroneayea>davexunit: aha!
<paroneayea>davexunit: are regular recursive processes somehow optimized in master in some interesting way?
<davexunit>there's no longer a fixed stack limit in master
<davexunit>the stack expands dynamically, so we can implement more things as their natural recursion rather than finding an iterative variant.
<paroneayea>davexunit: still, probably for the best you did it the way you did for efficiency reasons, if less for clarity
<davexunit>it's actually less efficient on master
<davexunit>wingo wrote about it
<davexunit>some time ago
<davexunit>I do see much reason to remove the stack limit if it meant people could more easily implement slower code :)
<davexunit>you can implement 'map' iteratively or recursively. the iterative version requires calling 'reverse' on the resulting list before returning.
<davexunit>which adds overhead
<mark_weaver>it's still better to ensure iteration in cases where the process wouldn't otherwise need to allocate O(n) storage.
<mark_weaver>e.g. for a procedure to compute the sum of a list of numbers, doing it recursively would be a huge lose for large lists.
<mark_weaver>but in the case of 'map', you need to build the temporary reversed list anyway.
<mark_weaver>*would need to
<davexunit>better to let the VM handle it :)
<davexunit>and let me write it the nice way
<taylanub>mark_weaver: (~ object field field2 field3) is valid, and works with set! too. so (set! obj field val) is really a synonym for the one-field case. I guess I'll remove it then.
<taylanub>hm, Per Bothner's idea of simply allowing (object field) and (set! (object field) value) is pretty clean as well, but implausible to implement as a library, and probably requires more intrusive changes to a Scheme implementation
<taylanub>meh, the difference is a tilde and a space. maybe One Day many implementations will adopt that variant and this SRFI will become obsolete; until then it could be pretty useful.
<daviid>I much much prefer the (set! (obj field) val) syntax as well :). am'I wrong thinking that the ~ is unnecessary here, since the parser can detect if there is/isn't a #\\( following set! ?
<mark_weaver>daviid: (set! (obj field) val) expands to ((setter obj) field value), and has for a long time.
<mark_weaver>where 'setter' is the core binding
<mark_weaver>we can't change that
<mark_weaver>what we can do, and already do in many cases, is to support (set! (field obj) value)
<mark_weaver>and we could probably arrange to make (set! (~ obj field) value) work also without too much trouble
<taylanub>(setter obj) could do something "smart" and return a procedure that will set a given field of obj if obj is a collection type instead of a getter procedure for a collection type, but that would be very awkward I guess
<daviid>ok, why is the ~ again? 'just' to allow field0 field1 ... ?
<mark_weaver>daviid: read this:
<daviid>I must be from the old school, I much prefer (slot-ref (vector-ref (hash-table-get pvhash 'prop) 0) 'name) to (~ pvhash 'prop 0 'name) :)
<daviid>and I prefer ref* to ~ fwiw
<daviid>(~ is a very weird thing to look at, it seems the code is thick :)
<mark_weaver>(set! (ref* ...) value) doesn't look very nice though, because it's not really a reference.
<mark_weaver>I probably won't use this myself, but it seems that some (many?) people would prefer it.
<mark_weaver>I worry too much about the efficiency impact of adding type-directed dispatch to otherwise very cheap operations like this.
<daviid>I won't use it either, and same here wrt efficiency impact. my only concern was to make sure, if it comes through, that it's been well though and does not 'break' goops
***dje is now known as dje42