guile-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: s-expressions, c, css and javascript


From: tantalum
Subject: Re: s-expressions, c, css and javascript
Date: Thu, 22 Dec 2016 17:57:54 +0000
User-agent: Posteo Webmail

Do you think deeper integration/compliance with scheme land would be best?

i think a source-to-source compiler like sc/sescript, that simplifies the use of another language, and scheme to machine code compilation are the two best ways for more run-time efficient code. otherwise there is likely overhead from mapping scheme semantics to a different language. i have seen programs that compile from scheme to others, including javascript, that add significant amounts of extra library code that has to be loaded to emulate basic scheme features in the target environment. for sc or sescript i could imagine an extension that implements more advanced code generation, like syntax-case macros and a module system, maybe as a separate project named "scx" or so. there would probably be no performance loss compared to using the lower-level language.

Did you try biwascheme?
yes :)  i tried biwascheme. it is a nice project.

so far i have not really used it because of the inherent overhead and because i did not want to make code dependent on an implementation more complex than a transpiler.

somebody could make a browser plugin that integrates a scheme compiler, as an alternative. this could tendentially be as fast as browser-native javascript engines. javascript code/libraries might not run on it and be incompatible though. afaik guile can share the same environment between different languages.

Do you have examples or documentation?

the homepage gives only a brief overview of plcss (http://sph.mn/content/e93). i am going to try to describe a few ways of using it (see the "eval" part in particular) and also attach some example code that is in current use at the end. i hope that helps.

# to use plcss in scheme code files
(import (sph lang plcss)) or (use-modules (sph lang plcss)) loads "plcss->css" and all other related bindings.

# from lists to ports with "plcss->css"
(plcss->css
  (quote ((".content" width "3px")))
  (current-output-port))

this writes the result css string to standard output. the first argument is a list of rules, which are lists but can also be plain strings.
the above is of course pretty much the same as

(plcss->css
  (list (list ".content" (quote width) "3px"))
  (current-output-port))

# from lists to strings with "plcss->css-string"
for example used in a procedure:

(define (create-css)
  (plcss->css-string (quote ((".content" width "3px")))))

(create-css)

# like quasiquote with "css"
note the (unquote a) in the second to last line.

(define a "4px")

(define css-result-string
  (css
    (".content"
(".mtime" position absolute right 0 top 0 color "hsl(0,0%,67%)" text-align right)
      (".signature" border "1px solid hsl(0,0%,70%)"
display "inline-block" border-radius (unquote a) padding "0.75rem" color "hsl(0,0%,10%)"))
    (".middle .content" padding 0)))

nested expressions always come after properties btw. so ("a" font-weight "bold" ("img" ...)) would be valid, but ("a" ("img" ...) font-weight "bold") would not. it makes things more consistent and easier to read.

# read from files
usually i write plcss in separate files and then read the files as scheme datums with the standard "read" procedure. the file content supports the full scheme syntax including scheme comments and all, which i find really nice.

so for example a file named "source.plcss" could contain the following

(".content" width "3px")
(".mtime" position absolute right 0 top 0 color "hsl(0,0%,67%)" text-align right)

an example for reading file content as scheme datums:
(call-with-input-file "source.plcss"
  (lambda (port)
(let loop ((e (read port))) (if (eof-object? e) (list) (cons e (loop (read port)))))))

should afaik nicely work with guile.

## simple command-line plcss compiler
these lines in a text file that is executable and run from a shell command-line make a basic plcss file compiler

#!/usr/bin/guile
!#
(import (sph lang plcss))
(plcss->css
  (let loop ((e (read (current-input-port))))
(if (eof-object? e) (list) (cons e (loop (read (current-input-port))))))
  (current-output-port))

example use:
  cat source.plcss | ./file-with-content-shown-above

# eval
we can take all this further and build something like a template processor with eval.

## with implicit quasiquotation
(import (rnrs eval))
(define plcss-data (eval (list (q quasiquote) plcss-data-list-read-from-file) (current-module)))
(plcss->css plcss-data (current-output-port))

now the plcss code inside files can contain (unquote) and (unquote-splicing) expressions and insert and access variables from the current module when it is evaluated with eval, or any other custom module that is passed as the second argument to eval. (environment (my module a) (another module)) can create environment/module objects, and guiles module reflection procedures are also useful. i am not sure how great these kinds of environment objects are from a programming language theory standpoint, but they can be useful.

## even further - implicit lambda
(eval (quasiquote (lambda (content) (unquote (list (q quasiquote) plcss-data-list-read-from-file)))) (current-module))

this is what (sph lang template) does: it gets s-expressions using scheme read, then builds a list with the symbol quasiquote at the beginning and puts that in a list that looks like a lambda expression, then evaluates this and it returns and actual procedure that we can call with arguments that can be used with (unquote) inside the file to create css. and another nice thing: it works just the same with sc, sescript and sxml.

to make this clearer, say we have a file with the following content

("body" background-color "#000"
  (".container" width "3px"))

we can now write

("body" background-color (unquote content)
  (".container" width "3px"))

in the file, and after having created the procedure with eval,

(our-procedure "green")

can be called wherever we like to give us a customised css (or xhtml, or javascript) string.

# plcss example files
& is for concatenation of nested selectors instead of separating them with a space. for example ("tr" (".a")) would create "tr .a {}" but ("tr" ("&.a")) creates "tr.a".

$ cat table.plcss
(".ascii" text-align left
  display inline
  ("&:not(:first-of-type)" margin-left "2rem")
  ("td, th" padding-left "0.5rem" padding-right "0.5rem")
  ("th" font-weight bold) ("td" font-style italic)
  ("td:first-child" font-weight bold font-style normal)
  ("tr" border-width "1px"
border-color "gray" border-bottom-style solid ("&:first-child" border-top-style solid)))

$ cat start.plcss
((".modification" ".alternatives") ("input" width "6rem" ("&[type=number]" width "3rem"))
  (".preview  .area" width "75px" height "75px"))

(".modification" ("> .control" display inline-block ("&:not(:first-child)" margin-left "1rem")))
(".preview .area" transition "background-color 0.25s ease")
((".conversion" ".modification > .preview") (".preview .area" width "503px" height "75px"))

(".alternatives" ("> *" display inline-block ("&:not(:first-child)" margin-left "1rem"))
  #;((".complement" ".greyscale") display inline-block)
(".greyscale" margin-left "1rem") (".hbox > *" ("&:not(:first-child)" margin-left "1rem")))

("#text_display_area" width "15rem" height "35rem")

(".conversion" ("label" display "inline-block" ("&:not(:first-child)" margin-left "1rem"))
  ("input" width "9rem"))

("@media (min-width: 140rem)"
(".middle" column-count 2 -moz-columns 2 columns 2 -moz-column-count 2 -webkit-column-count 2))


---
On 2016-12-21 19:32, Amirouche Boubekki wrote:
On 2016-12-07 23:43, tantalum wrote:
hi

last time i mentioned it was a few years ago, and i just thought i let
you know that sph-sc got some interesting updates recently, and plcss
and sescript (as well as sph-lib) are still actively maintained.


I started playing with Guile because of your mail :)


"sescript" is very similar to sc, it is like sc but for javascript or
ecmascript. javascript on its own already feels more like scheme than
c because of its use of anonymous first-class functions. sescript adds
features like "let", implicit return and even an r6rs library form.
sometimes i was able to copy code between scheme and sescript without
change because it is so similar.

Do you think deeper integration/compliance with scheme land would be
best? Did you try biwascheme?

"plcss" creates css. it is written in less than 90 lines of scheme
(but imports a few bindings) and can offer most features of or more
than tools like sass and lesscss.

That look like something I could put to use. Do you have examples or
documentation?

for details and examples, here links to the project homepages:
sc: http://sph.mn/content/3d3
sescript: http://sph.mn/content/413
plcss: http://sph.mn/content/e93

while we are at it, i recently made a time and calendar calculation
library from scratch (which was pretty difficult, if anyone wants to
check out how this can be done, see the "time" libraries in sph-lib
(http://files.sph.mn/sourcecode/sph-lib/)) and this went into the
calendar on http://ytilitu.xyz/ , which runs on guile.

Looks cool and useful :)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]