Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
    urbanchr
    @urbanchr

    But note that I tried this consistent behaviour out under the following two versions of Ammonite:

    Linux: Ammonite Repl 2.1.4 (Scala 2.13.2 Java 11.0.7)
    MacOSx: Ammonite Repl 2.2.0 (Scala 2.13.3 Java 9)

    These were just randomly installed on these computers.

    Philipp Dörfler
    @phdoerfler

    Hi! Given:

    def mkParam(p: Param): Term.Param = q"${p.value}: String"

    and

    for {
    …
        params   = matched.params.map(mkParam)
    } yield q"def $name($params): Response = client.$method($path)"

    I run into two issues:

    error: type mismatch;
     found   : meta.Term.Ascribe
     required: scala.meta.Term.Param
    def mkParam(p: Param): Term.Param = q"${p.value}: String"
                                        ^

    and

    error: type mismatch when unquoting;
     found   : List[scala.meta.Term.Param]
     required: scala.meta.Term.Param
      } yield q"def $name($params): Response = client.$method($path)"
                          ^

    I did not find documentation about how to construct interpolated quasi quote strings to create parameter lists for def and how to create Parameters in general. How do I do this and/or where in the documentation is this?

    Ólafur Páll Geirsson
    @olafurpg
    @phdoerfler
    what happens if you do param"${p.value}: String" instead of q"${p.value}: String"?
    Philipp Dörfler
    @phdoerfler
    I can do that? O.o
    Ólafur Páll Geirsson
    @olafurpg
    This compiles
    @ def mkParam(p: Term.Name): Term.Param = param"${p}: String"
    Philipp Dörfler
    @phdoerfler
    oh wow I had no idea, yeah it does
    thanks! That leaves me with the other problem, still
    error: type mismatch when unquoting;
     found   : List[scala.meta.Term.Param]
     required: scala.meta.Term.Param
      } yield q"def $name($params): Response = client.$method($path)"
                          ^
    Ólafur Páll Geirsson
    @olafurpg
    @ val params = List(param"a: Int", param"b: String")
    params: List[Term.Param] = List(
      Term.Param(List(), Term.Name("a"), Some(Type.Name("Int")), None),
      Term.Param(List(), Term.Name("b"), Some(Type.Name("String")), None)
    )
    
    @ q"def foo(..$params) = a".syntax
    res7: String = "def foo(a: Int, b: String) = a"
    add .. before $params
    Philipp Dörfler
    @phdoerfler
    most excellent @olafurpg thanks a lot! I feel like I missed some essential part in the documentation
    Ólafur Páll Geirsson
    @olafurpg
    Those references are quite dense
    Philipp Dörfler
    @phdoerfler
    sometimes, I am too :P
    ah, yes, I see it now. Thanks again! Seems that the documentation was meant to be read slightly different than how I browsed it
    Philipp Dörfler
    @phdoerfler
    image.png
    OK, so, how do I construct a Term.Name using string interpolation? When I do this, all I get is a Stat
    method: Term.Name = q"${someString.toLowerCase}" is what I do

    I also, in my neverending wisdom, tried adding <>:

    error: type mismatch when unquoting;
     found   : String
     required: scala.meta.Term.Name
        method: Term.Name   = q"<${someString.toLowerCase}>"

    to no avail.

    error: type mismatch;
     found   : scala.meta.Stat
     required: scala.meta.Term.Name
        method: Term.Name   = q"${someString.toLowerCase}"
    oh, I see it now. The example doesn't actually have a $ sign. Oh my
    Guess I have to create them manually
    Ólafur Páll Geirsson
    @olafurpg
    Term.Name(String)
    There are some cases where you can interpolate a string and it's interpreted as a term name
    but it's usually simplest to use Term.Name(String) if you know you need a term name
    Philipp Dörfler
    @phdoerfler
    I see. Yeah, Term.Name(String) is what I have been using so far. I was just curious since the table in the docs makes it look like q"" can (reliably) be used for this
    I gotta say scalameta is really cool and it's fun to use :)
    Ólafur Páll Geirsson
    @olafurpg
    you can construct literal term names with quasiquotes
    q"a" becomes Term.Name("a")
    Ólafur Páll Geirsson
    @olafurpg
    I added a note in the quasiquote spec about using Term.Name when interpolation is needed scalameta/scalameta@4e5dabd
    Ólafur Páll Geirsson
    @olafurpg
    @urbanchr the issue appears to be caused by this line in Ammonite where it adds scalameta 4.3.20 to the classpath by default https://github.com/lihaoyi/Ammonite/blob/master/build.sc#L205
    urbanchr
    @urbanchr
    @olafurpg: Thanks a lot for digging into that.
    Jakub Kozłowski
    @kubukoz
    Has anyone tried to implement a hoogle after Scalameta happened? Last time I saw it implemented was somewhere in 2016 and it was incomplete or inaccurate. Looks like semanticdb could change the landscape a bit.
    There are some obviously non-trivial problems to solve, like how do you treat implicits, etc., but it looks like we're closer to a possibility of having that than back then
    Ólafur Páll Geirsson
    @olafurpg
    @kubukoz it’s been asked several times but i’m not aware of any implementation.
    sudheer
    @psudheerhh
    hi all, I'm trying to use scalameta for code generation. i have referred documentation multiple times. is there a sample example that covers all the features of how to use it? any help is greatly appreciated, thx! (also on a side not, i have never used macros before. would that be a blocker?)
    Ólafur Páll Geirsson
    @olafurpg
    @psudheerhh i recommend using something like typelevel/paiges for code generation instead of scalameta
    1 reply
    Tilman Zuckmantel
    @tizuck
    Hey guys, i am just getting the hang of scala meta. I am interested in visiting each tree node and folding it into a new type. Something like a fold method for trees. The closest i have found is the tree traverser but it is restricted to the type Unit. Is there anything like this:tree.foldLeft[B](z:B)(op: (B,tree) => B):B ? Or some method to simulate this behaviour?
    Ólafur Páll Geirsson
    @olafurpg
    Tilman Zuckmantel
    @tizuck
    @olafurpg Transformers apply method override def apply(tree: Tree): Tree is restricted to the type Tree. So i can only transform tree classes into other valid tree classes. But i'd like to transform them into my own type. What i really want is something like having a tree and counting the number of traits inside the tree. So i would want to recursively add 1 on each tree node representing a trait. I think it might be possible using a context class (in the example this would be counter:Int) in a traverser that simulates the accumulator in foldleft. Edit: In the example i want this behaviour: tree.foldleft(0){ (t,i) => if(t equals ("trait")) i + 1 else i }
    Ólafur Páll Geirsson
    @olafurpg
    In these situations I normally use mutable fields combined with Traverser
    class MyCustomTraverser extends Traverser {
      var i = 0
      def apply(n: Tree): Unit = ...
    }
    val t =new MyCustomTraverser()
    t.traverse(myTree)
    val myResult = t.i
    You can probably implement a purer wrapper around that pattern
    I normally write a helper method that wires everything together so that the mutability doesn't leak
    def computeFoo(t: Tree): Foo {
      val t = new MyFooTraverser()
      t.traverse(t)
      t.result()
    }
    Tilman Zuckmantel
    @tizuck
    Thx for the suggestion! I usually don't like working with mutable fields. As i look through Trees.scala it could also be possible to actually implement a foldLeft function on the tree nodes that interest me myself. I might give that a try. Maybe it would be worth it considering to implement some kind of generic Visitor Pattern on tree notes ? I like for example the way ANTLR4 makes use of the Visitor Pattern :)
    Hugo van Rijswijk
    @hugo-vrijswijk
    Maybe collect is what you're looking for?
    Ólafur Páll Geirsson
    @olafurpg
    @tizuck as suggested by @hugo-vrijswijk, you can use .collect for simple tasks like counting the number for trees matching a given pattern.
    I agree the visitor pattern is a very nice way to build values from a tree traversal. It's not on the roadmap to implement this for scalameta, but I suspect it wouldn't be too hard to implement on top of the Traverser class similar to how Tree.collect() implements a pure API on top of Traverser
    Tilman Zuckmantel
    @tizuck
    @hugo-vrijswijk @olafurpg i can achieve what i want by using collect . For each node i now first call collect on each child passing a custom operation and then perform the operation on the node itself. This way i can write a custom recursion on the tree. Thx for the suggestion ! It is a bit hacky because at the end i get a List as a result of collect but all i need is a single value return, but it'll do.