<mark_weaver>also note that (let ((v1 e1) (v2 e2) (v3 e3)) ...) is equivalent to ((lambda (v1 v2 v3) ...) e1 e2 e3) <linas>OK, let me try my question again ... <linas>for example: (define (show-expr x) (display x)) and (show-expr '(+ 40 2)) clearly prints (+ 40 2) as expected. <linas>Is there a way to define some function (define (func x) ...) so that (func (+ 40 2)) prints (+ 40 2) anyway? (Notice the absence of the quote) <mark_weaver>linas: a normal procedure cannot do that. 'func' would need to be a macro to do that. <linas>iI was afraid you'd say that. ... <mark_weaver>in a procedure call (<proc> <arg> ...), all elements of that list are first evaluated in an unspecified (but serializable) order. <mark_weaver>and then the result of the first expression must be a procedure that is applied to the evaluated arguments. <linas>yes, for scheme, I know. I'm actually solving this problem in a different language, and am looking for inspiration <jmarciano>mark_weaver: thanks. I am reading that let variables cannot be reused in the bindings list, while let* variables can. <linas>but with a macro, Hmm. I guess one just puts an ordinary quote in there, the macro beta-reduction performs the replacement, but the quote halts the evaluation ... <mark_weaver>jmarciano: right, see the let/lambda equivalence I gave above. when a let tries to bind the same variable twice, that involves defining a procedure that has two formal arguments with the same name. <iyzsong>doesn't the arguments evaluated from left to right? it's called applicative-order as i see in SICP. <mark_weaver>iyzsong: no. applicative order means that all of the arguments are evaluated before the procedure is applied. <jmarciano>my mind is not so clear... I have to practice. <mark_weaver>iyzsong: in scheme, all of the elements of a procedure call (including the first element, the procedure expression) can be evaluated in any order. <mark_weaver>once a given element starts evaluating, it evaluates to completion before any other element starts to be evaluated. <mark_weaver>iyzsong: however, in guile, it might currently be the case that the arguments are always evaluated left-to-right. <mark_weaver>but I'm not 100% sure about that, and I wouldn't count on it remaining true in the future <mark_weaver>linas: one thing to be aware of: if you quote the expression, then you won't be able to evaluate it properly. <iyzsong>ok, so the spec doesn't say about it for good reason, but implementations tend to use a simple one ;-) <mark_weaver>linas: if you want to make macros that act sort-of like procedure but have access to the bare expressions, then the thing to do is to pass both the _syntax-object_ (i.e. quote it with 'syntax' instead of 'quote'), and a lambda expression that can be used to evaluate it if desired. <mark_weaver>'quote' discards syntactic information needed to maintain hygiene in the macro expander <mark_weaver>linas: for details on how our macro expander works, and the extra information that is lose by 'quote', see "Syntax Abstraction in Scheme" by R. Kent Dybvig, Robert Hieb, and Carl Bruggeman. <mark_weaver>linas: to get an idea of why this is important: (or x y) expands to (let ((t x)) (if t t y)) <mark_weaver>here 't' is introduced in the macro template, and the syntax object that represents that 't' includes a mark that is unique to that macro expansion <mark_weaver>in code that uses macros like this in nested fashion, you often end up with multiple occurrences of the same variable name that must be distinguished from each other or else you will suffer from "unintended variable capture" <mark_weaver>'syntax' creates a syntax-object which can be inspected and deconstructed using 'syntax-case', and identifiers (syntax-objects corresponding to symbols) can be compared using 'free-identifier=?' and 'bound-identifier=?'. <linas>mark_weaver the keyword 'syntax' -- do you know if other languages use that, or if they have something analogous, and what it would be called? <linas>I can't really think of other languages that have hygenic macrs <linas>I guess maybe C++ templates are vaguely like hygenic macros in a way. <linas>but I don't want to go there. <mark_weaver>by the way, just as ' is an abbreviation for 'quote', #' is an abbreviation for 'syntax', and most of the time the abbreviation is what's used <mark_weaver>note it is two characters, '#' followed by apostrophe <mark_weaver># is a prefix used for many lexical syntaxes in scheme <mark_weaver>and there's also 'quasisyntax' (#`), 'unsyntax' (#,), and 'unsyntax-splicing' (#,@) which are analogous to quasiquotation but for syntax objects. <mark_weaver>guile has an unusual feature: it allows lexical environments to be captured as first-class objects (using 'the-environment'), and then arbitrary expressions can be evaluated within those environments using 'local-eval'. <mark_weaver>depending on what you're doing, it might be of interest. <mark_weaver>although it should be noted that the use of 'the-environment' drastically reduces the amount that our optimizer is able to do in that lexical environment to almost zero. <mark_weaver>because normally, variables can only be mutated by a 'set!' within that lexical environment. if none appears, then the compiler can assume the variable is immutable, which is highly beneficial for optimization. <mark_weaver>but if 'the-environment' is used within the scope of a lexical variable, then the compiler must assume the variable might be mutated at any time. <linas>My actual problem is not a scheme problem; I can't actually use scheme to solve it; mostly, i'm trying to understand enough of how scheme does it, so that I can pick a non-stupid solution. <mark_weaver>out of curiosity, why can't you use scheme to do it? <mark_weaver>the reason I ask is that maybe I can think of a way to do it in guile, or maybe it wouldn't be hard to add the necessary functionality to allow it. <linas>Due to a historical accident, I find myself in a position of maintaining and inventing a kind-of language. I'm vaguely embarassed about talking about it because it has so many obvious problems. <linas>its a kind-of-like mashup of prolog and scheme, but with types, so maybe haskell-like-ish but with 1/1000th the performance of haskell <linas>Its .. a mess but it *my* mess <linas>trick is to fix things without loosing backwards compat <mark_weaver>there's typed racket, and prolog functionality can be embedded within scheme in several ways, my favorite of which is mini-kanren <mark_weaver>we should probably incorporate something similar to typed racket into guile at some point <linas>the deal for me is not that I need prolog,; what I really need is a graph data-store (with s-exprs and logic as a special case of 'graph') <mark_weaver>some of the recent stuff they've done with mini-kanren is implementing an evaluator in it, and using it to automatically generate all quines <linas>some of the graphs are evaluatable <linas>and another key feature is the ability to do graph re-writing. <linas>so, graph rreiwriting is vry much like patter-matching in scheme or racket, slightly more general, <linas>and the result of a pattern match is then beta-reduced into another pattern to create a new graph <mark_weaver>well, so far I've not heard anything that couldn't be done within a scheme environment, possibly with a custom evaluator with extra functionality <linas>So .. a rule-engine, but the rules are graphs. <linas>and the historical accident is that it wasn't <linas>and now that its not... its hard to get there from here. <mark_weaver>one feature that racket has that we could add easily is that ordinary procedure applications (<proc> <arg> ...) are automatically rewritten as a macro call to a macro of your own design. <mark_weaver>so you can essentially customize the semantics of procedure calls trivially. <mark_weaver>linas: okay, since you used the word "invent", I thought maybe you were in the position to create it how you wished. <linas>I have a user-base and a large amount of application code that can't be discarded <linas>heh. it *is* opencog... or rather, opencog is my "user base" <linas>we're now calling the core graph-language "atomese" <mark_weaver>and the core language is complex enough that it would be difficult to rewrite in scheme in such a way that the existing code would continue to work? <linas>atomese expressions are alwways graphs, they are sometimes evaluatable, there is a rule-engine to apply graph-rewriting rules which are themseleves expressed as 'atomese'. <linas>well, its difficult because .. the pattern matcher is written in C++ .. the forward and backward chainers are written in c++. The dtabase backends are written in C++. It has scheme, python and haskell bindings. <linas>If we had 5 guys and a year or two, it could be re-written <linas>but the core problem is: we're groping around for what it should even be. We haven't figured out the "correct paradigm" yet <linas>we know it has to be kind-of like rule-engine + graphs + (bayesian) logic but it'sfuzzy after that <mark_weaver>I wish I had more time. OpenCog is fascinating and probably quite important, but I'm already overloaded and it would surely take me a long time to come up to speed on this. <mark_weaver>many years ago a friend explained the basic concepts of opencog, iirc "hypergraph" was a term used at that time. <mark_weaver>the ideas in scheme, which I'm well versed in, would probably be of some value here. <mark_weaver>linas: btw, are you familiar with Sussman's recent work on "propagators" ? <linas>I tried implementing an opencog variant of it <linas>I like the idea, it was a little harder than expected <linas>I had problems with muxing and demuxing multiple connections. <linas>I liked the idea in general, didn't have the time to do the comp-sci research at that level <mark_weaver>well, hygienic macros might be a useful layer on top of whatever you come up with. <mark_weaver>although scheme is the only language I know of that has them, they could be easily adapted to any lexically-scoped language. <linas>the pattern-matcher/rule-engine thing is essentially a kind-of macro langauge <mark_weaver>although pattern matchers are commonly associated with macro systems, they are orthogonal <mark_weaver>'syntax-case' can be used anywhere, not just within so-called 'syntax-case' macros. <mark_weaver>from the point of view of the core macro system, macros are just procedure that accept a syntax object of the macro use, and return a transformed syntax object of its replacement. <linas>If I blur my eyes, what you call "macro", I call "rule" <linas>and I think that's quite correct: what you call "syntax object" is what I call "graph" <mark_weaver>do the graphs contain anything analogous to identifiers that refer to each other, in a similar way that variable references in scheme code refer to bindings? <mark_weaver>I guess I'm trying to determine whether the problems that we've overcome with hygienic macros have any analogue on your world. <linas>.. yes, in two different, unrelated ways. <linas>there are explicit variables in the templates <linas>and recently, we added a 'define' because people wanted that, but my 'define' is just sugar <mark_weaver>do these variables have limited scope, e.g. lexical scope or anything analogous to that? or does every variable have global scope? <linas>hygenic .. yes, there was some confusion about that at first, but I beleive everything is now 'hygenic' -- variables don't leak out where they're not supposed <mark_weaver>linas: this was the seminal paper on hygienic macro expansion: ftp://www.cs.indiana.edu/pub/techreports/TR194.pdf <mark_weaver>it might be worth a read just to make sure that you didn't miss anything. <linas>except .. they're not really "macros" -- they don't really get "expanded". They are "rules" that rewrite thier input and convert it into their output. <mark_weaver>the solution given in that paper has efficiency problems that were later addressed <mark_weaver>I'm not sure what is the difference between "expand" and "rewrite". <mark_weaver>in normal english, the word "expand" implies that the output is larger than the input, but of course that's not the case for macro expansion. <mark_weaver>unintended variable capture is only one of the problems that is solved by hygienic macros <linas>what I have is a pool, a 'database' of graphs. I pick a rule (macro) and apply it to everything in that pool that matches it. If so, <mark_weaver>another is when a template in a macro definition references a variable whose scope includes the macro definition, but does not include the macro use. <linas>If so, then I expand/rewrite, and the result of that is stuffed back into the pool (and the orginal input is NOT removed, it stays there as well) <mark_weaver>those are notable differences, but I don't think they reduce the applicability of the work on hygienic macros. <linas>as I said ... it could all be redesigned, its all a historical accident, and we don't really know what we're doing :-) <mark_weaver>my lack of knowledge in your problem area limits how much I can help, but I get the impression that the lessons of hygienic macros are worth your attention. <mark_weaver>because they seem very widely applicable in computer languages <linas>ahhh yes, this circles back to my orginal question: so, yes, I have macros... BUT, in many cases, I have to ALSO evaluate expressions duringthe macro expansion <linas>well, my problem was that something was getting evaluated, when it should not have been, it merely should have been expanded <mark_weaver>macros need to be expanded starting from the outermost expression, because that is the only expression for which the context is known. <linas>for my exapnsion, I have to support this: "if the syntax/template matches, and also these expressions evaluate to true, then perform the macro expansion" <linas>and by default the arguments to the expressions are evaluated as well, but sometimes, I only want to pass the syntax in, and not evaluate them. <linas>and "quasi-syntax" is more or less exactly what I need. <linas>i.e. a quote .. except I can't say "quote variable x" because I do want to know what x is, i just don't want to evaluate it. <mark_weaver>do you need to see the code itself, or just postpone evaluation? <linas>so "quasisyntax variable x" seems to do the trick <mark_weaver>because in scheme we could accomplish that by wrapping the operand with (lambda () ...) <linas>I want to see the "code" itself. <linas>OK, so my variable x gets bound fo a DefinedSchema which is bound to a lambda, and the bug report is that the lambda is getting evaluated when they don't want it to be. <mark_weaver>so, in a scheme macro, the subexpressions have not yet been macro-expanded, so seeing the code is not much use because if you don't understand all the macros you can't make sense of it. <mark_weaver>but in your world, maybe the analogue of macros are not nested? <mark_weaver>we have some complications in the scheme world that might not exist in your world. <linas>my "variable x" gets bound when the template is matched. <mark_weaver>in scheme, since the same simple data structure (lists) are used to represent both expressions and other things like literal data and binding lists in 'let' expressions, etc, we can't tell ahead of time which operands of a macro will become expressions and which will become binding lists or literals. <linas>if the template matches, then the variable portions of the template get passed into explcit variables, which can then be a part of an evaluatable expression. <mark_weaver>for that matter, a scheme macro might use a program to dynamically generate code in some arbitrary way based on bits that it finds in its operands. <r6ku>are there more applications that use guile besides the ones listed on the main page? <mark_weaver>r6ku: oh yes, there are more than I could possibly list <mark_weaver>linas: I'm seeing now some fundamental differences of note: in scheme, macro expansion is completed before evaluation begins, and has no access to run-time information of the code it is working on. <mark_weaver>and it really can't, because the code that's being expanded might be within a loop or a procedure that hasn't even been called yet. the macro expansion happens only once, but the procedure might be called any number of times. <mark_weaver>I'll need to think about how this affects the applicability of these ideas, or how they might be adapted. <linas>whereas I'm alternating between macro expansion and execution, and even using execution do decide if a macro should be expanded. <linas>well, step back and look at it form this perspective <mark_weaver>sure, it makes sense in your context, I can see that. <daviid>mark_weaver: if you need to return an empty list, do you use '() or (list) <linas>look up "rule engine" on google of wikipedia and you'll see things like drools and jboss buusiness rule engine, and some fairly boring stuff <mark_weaver>daviid: either would work, but you might as well use '() <linas>so if I click randomly, I see this: <linas>and now make the mental connection "a rule is a macro" <linas>and then you see what i'm dealing with ... <linas>inference engine is closest to what I have: <mark_weaver>I have to go afk, but I'll mull this over and see if I can come up with any suggestions of things to think about. <linas>that article says "IF <logical expression> THEN <logical expression>" except my if-tehn are "macros/rules" <linas>ok, yeah I talked too much already ***wleslie is now known as pa_simpson
***pa_simpson is now known as wleslie
***karswell` is now known as karswell
<Jookia>Is there a smaller version of Guile than guile-static-stripped as found in Guix? <jmarciano>how to delete single emacs windows on bottom, without touching others? <jmarciano>but how to delete just one, below or right, if I have 6? <davexunit>ACTION thinks about what a websocket client in Guile should be like <davexunit>ideally, it would be implemented as a custom port, but I don't think the websocket protocol doesn't really accodomates this. <davexunit>with websocket, you send over "frames" of data. if I were to use 'write' to write an sexp to the websocket, there's no way to know that the frame has been completed and to send it. maybe with a special flush operation? <rain1>how do you do the equivalent of: void *x; f(&x) ? <wingo>rain1: the first level of pointers corresponds to a bytevector <wingo>e.g. char* -> bytevector of char <wingo>so you would call f with the bytevector of char(s) as the argument <wingo>void ** -> bytevector of void* <wingo>so you pass as the argument a bytevector which holds one void* value (either 4 or 8 bytes) <rain1>I tried to create a bytevectore with %null-pointer in it but that gave an error <rain1>I could make one with size 8 and fill with the 0 byte I guess.. <wingo>assuming your pointers are 8 bytes wide <rain1>thank you im trying it out :) <rain1>(null-pointer? (bytevector->pointer vec)) <rain1>but I feel a bit confused about the dereference levels <davexunit>rain1: there's a special %null-pointer object <rain1>there is dereference-pointer for * <rain1>but what is the equivalent of &? <rain1>(address->pointer (pointer-address p)) or is that just the identity? <rain1>sorry make-pointer, not address->pointer <davexunit>rain1: certain objects can be easily converted to pointers, like strings and bytevectors <rain1>thats what im trying, line 56 is supposed to be the guile equivalent of line 14 <rain1>but I think its not because it doesn't detect error <rain1>(= 0 (pointer-address (dereference-pointer err))) <rain1>but i feel like I shouldn't be using 0 <lloda``>conversion is not the right word for what bytevector->pointer does <davexunit>-> means conversion. let's not get pedantic. <rain1>how do I increment a pointer? like p += 8; ? <rain1>I guess I can go through pointer-address and back <davexunit>or whatever the unit is, I guess C's pointer arithmetic will increase by sizeof(type) bytes <lloda``>it's not pedantic. The -> is badly used in this case <holomorph>hm! can't bind sockets in abstract namespace <rain1>(with-output-to-string (lambda () (system* "guix" "build" "gobject-introspection"))) <rain1>that gave me the empty string.. but it printed the text <rain1>how do you get that text as a string? <civodul>rain1: with-output-string cannot work for that; you need to use open-input-pipe and the likes <civodul>however, note that the "guix build" command has a corresponding Scheme procedure: 'guix-build' in (guix scripts build) <rain1>ah! that makes it 10x easier, thank you <berndj>mark_weaver / others: after playing some more with my GUILE_FLAGS vs AC_CHECK_HEADERS test case, it seems guile is an innocent bystander here; deep down the macro call chain AC_EGREP_CPP gets called, the exhibits the same behaviour <jmarciano>may I dare to ask... is there Guile for Android? <davexunit>but never saw any working application or anything like that <jmarciano>I could use the smaller device to learn Guile on the go <davexunit>I would love an android app that ran a guile repl that I could play with while I'm on the train or whatever <jmarciano>only that Android is full of non-free software. <davexunit>right, every android distribution except for Replicant has non-free software in it. <davexunit>I don't actually like Android, but it's what I use. F-Droid helps make it a bit better. <davexunit>my dream for a phone OS probably will never happen so long as the GSM baseband firmware and drivers remain a secret. <jmarciano>I found Asus Transformer, not used it for 1.5 years, removed all, restarted, and using only f-droid, without any Google stuff. <davexunit>the FCC is about to ruin WiFi, so I don't see much hope for GSM... <jmarciano>I realized I don't need Android, just small laptop on the go <jmarciano>I will bring this Asus Transformer to the shop to change for some computer. <jmarciano>my mother in law will be happy with new computer... <jmarciano>I remember, I felt like under pressure to put Google account. Did not know it is not needed. <jmarciano>and now I have observed better its startup -- first thing is: download Flash from Adobe... <jmarciano>and "for security" I should not download anything else but from Google Play Store... <rain1>typedef struct { } GIAttributeIter; // An opaque structure used to iterate over attributes in a GIBaseInfo struct. <rain1>this is weird, I guess it has fields but they wont show us in documentation what they are <rain1>in this example they do GIAttributeIter iter = { 0, }; <rain1>I was wondering how to do with guile ffi, i tried (iter (make-c-struct (list '*) (list %null-pointer))) <rain1>but maybe it has extra uninitialized fields <rain1>If I set it to hold four pointers like in this code, it still segfaults <jmarciano>If I cannot run Guile on it, I am not running nothing. <rain1>I wish there was a free software and hardware phone <jmarciano>rain1: there is, the talkie-walkie, I have 2 here, for me and my wife, mother in law, children... very nice. No fees. <jmarciano>It is possible to set up radio station, that calls people over fixed line. With mobile talkie-walkie, one can then dial any number and call other people. 5-10 km away from station only. <rain1>that's sounds like fun to set up <jmarciano>Hand-held radio station, with numbers to dial. It is not as small as some phones. But you pay no mobile charges, just eletricity for battery. <jmarciano>$200 used, for zero-fees... but no support for Guile <rain1>but imi not sure if these technique are very widely used in scheme <rain1>what is the situation with guile-gir? <daviid`>rain1: guie-gir is 6 or 7y unmaintained. also, it used the old ffi, so not good <daviid`>rain1: what's your need exacyly, wrt gnome I mean? (just curious) <rain1>I wanted to make a linux gui program in guile <rain1>if i extend it maybe it will be useful to interface with gtk3 <daviid`>rain1: cool. I just started to write a gir binding too, but i did not want to tell anyone yet :) because it's going to take quite some time before it's usable... the ultimate goal is to fully integrate with goops, like guile-gnome does it <daviid`>mark_weaver: it will take at least a year before anything really good comes out, so nobody should hold his breath here :) <daviid`>rain1: did you consider using taylan bytevectors? <rain1>well since you're already doing this <rain1>I shouldn't duplicate effort <daviid`>rain1: i was asking if you did think about using taylan bytevectors when you wrote your girepo...? <daviid`>rain1: we can coordinate our effort here, but I need a bit more thinking about how I wan't to do it... right now i'd call my toy 0.0.1-alpha and everything subject to change at anytime ... but it's good to know your are interested, I can ask for help ... :) <rain1>taylans library looks great as usual <daviid`>rain1: I'm interested in your skill, and ideas about using taylan lib precisly for the gir project <daviid`>the code you pasted, if you have time, I would be happy to see it but using taylan bytevector lib, as an experiment, wdyt? <rain1>why bytestructures rather than guiles regular ffi struct thing? <rain1>define-wrapped-pointer-type specifically <daviid`>i don't have much knowledge in this area, but it seems to be an abstraction level building the GType/GObject [bootstrap] that gobject introspection needs could benefit <daviid`>rain1: why not? i'd love to see a simple try with both appraoches and an opinionated opinion if it is better, or if the regular ffi struct are good enough? <daviid`>I said GType/GObject 'bootstrap' because once we have a working gir, obviously the full Glib and Gobject are fully binded using there gir material <rain1>yeah i like the sound of that! <rain1>would be super to automatically get bindings to libraries <daviid`>rain1: you should go ahead with your paste and continue till you have a working helo world [gtk] working example, and paste again <daviid`>I'm interested to see how you would do it ... <cojy>i remember wingo mentioning HAMT data structures for the compiler in a blog, are this available as a guile library anywhere? <davexunit>you can access them, but don't expect compatibility between releases <davexunit>Guile needs a public API for these kinds of functional data structures.