Skip to content

Commit

Permalink
Object.transformFields/transformValues
Browse files Browse the repository at this point in the history
  • Loading branch information
mdr committed Mar 27, 2017
1 parent e0ecb9b commit 0e4a812
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
v0.0.8 (..)
-----------

* Object.transformFields/transformValues
* Url.open
* Url.withQueryParams, http.XXX --queryParams={}
* os.delete deletes paths bottom up
Expand Down
2 changes: 2 additions & 0 deletions src/main/scala/com/github/mdr/mash/ns/core/ObjectClass.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ object ObjectClass extends MashClass("core.Object") {
HasFieldMethod,
HoistMethod,
MapMethod,
TransformFieldsMethod,
TransformValuesMethod,
UnblessMethod,
WithFieldMethod,
WhereMethod,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.github.mdr.mash.ns.core.objectClass

import com.github.mdr.mash.evaluator.ToStringifier
import com.github.mdr.mash.functions.{ BoundParams, MashMethod, Parameter, ParameterModel }
import com.github.mdr.mash.ns.core.ObjectClass
import com.github.mdr.mash.runtime.{ MashObject, MashString, MashValue }

object TransformFieldsMethod extends MashMethod("transformFields") {

object Params {
val F = Parameter(
nameOpt = Some("f"),
summaryOpt = Some("Function used to transform field names of the object"),
descriptionOpt = Some(
"""The function may take up to two arguments. If it takes only one argument, the field name is provided.
| If takes two, the field name and value are provided.""".stripMargin))
}

import Params._

val params = ParameterModel(Seq(F))

def apply(target: MashValue, boundParams: BoundParams): MashObject = {
val obj = target.asInstanceOf[MashObject]
boundParams.validateFunction1Or2(F) match {
case Left(f)
MashObject.of(obj.immutableFields.map { case (name, value)
ToStringifier.stringify(f(MashString(name))) -> value
})
case Right(f)
MashObject.of(obj.immutableFields.map { case (name, value)
ToStringifier.stringify(f(MashString(name), value)) -> value
})
}
}

override def typeInferenceStrategy = ObjectClass

override def summaryOpt: Option[String] = Some("Return a new object with the field names transformed")

override def descriptionOpt = Some(
"""Examples:
| { foo: 3, bar: 4 }.transformFields (.toUpper) # { FOO: 3, BAR: 4 }""".stripMargin)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.github.mdr.mash.ns.core.objectClass

import com.github.mdr.mash.functions.{ BoundParams, MashMethod, Parameter, ParameterModel }
import com.github.mdr.mash.ns.core.ObjectClass
import com.github.mdr.mash.runtime.{ MashNumber, MashObject, MashString, MashValue }

object TransformValuesMethod extends MashMethod("transformValues") {

object Params {
val F = Parameter(
nameOpt = Some("f"),
summaryOpt = Some("Function used to transform values of the object"),
descriptionOpt = Some(
"""The function may take up to two arguments. If it takes only one argument, the value is provided.
| If takes two, the field name and value are provided.""".stripMargin))
}

import Params._

val params = ParameterModel(Seq(F))

def apply(target: MashValue, boundParams: BoundParams): MashObject = {
val obj = target.asInstanceOf[MashObject]
boundParams.validateFunction1Or2(F) match {
case Left(f) MashObject.of(obj.immutableFields.mapValues(f))
case Right(f) MashObject.of(obj.immutableFields.map { case (name, value) name -> f(MashString(name), value) })
}
}

override def typeInferenceStrategy = ObjectClass

override def summaryOpt: Option[String] = Some("Return a new object with the values transformed")

override def descriptionOpt = Some(
"""Examples:
| { foo: 3, bar: 4 }.transformValues (n => n * n) # { foo: 9, bar: 16 }""".stripMargin)
}
Original file line number Diff line number Diff line change
Expand Up @@ -1086,6 +1086,14 @@ class EvaluatorTest extends AbstractEvaluatorTest {
"{ apple: 1, bob: 2, cat: 3 } | map (f v => { (f.toUpper): v * v })" ==> "{ APPLE: 1, BOB: 4, CAT: 9 }"
"{ apple: 1 } | map (f v => { (f): v, (f.reverse): v })" ==> "{ apple: 1, elppa: 1 }"

// Object.transformValues
"{ foo: 3, bar: 4 }.transformValues (n => n * n)" ==> "{ foo: 9, bar: 16 }"
"""{ foo: 3, bar: 4 }.transformValues (f v => "$f$v")""" ==> "{ foo: 'foo3', bar: 'bar4' }"

// Object.transformFields
"{ foo: 3, bar: 4 }.transformFields (.toUpper)" ==> "{ FOO: 3, BAR: 4 }"
"{ foo: 3, bar: 4 }.transformFields (f v => f.toUpper + v)" ==> "{ FOO3: 3, BAR4: 4 }"

// Object.grep
"{ foo: 'wibble', bar: 'wobble', wibble: 'baz' }.grep 'wibble'" ==> "{ foo: 'wibble', wibble: 'baz' }"
"{ foo: 'wibble', bar: 'wobble', wibble: 'baz' } | grep 'wibble'" ==> "{ foo: 'wibble', wibble: 'baz' }"
Expand All @@ -1106,4 +1114,5 @@ class EvaluatorTest extends AbstractEvaluatorTest {

// Url.host
"net.url 'http://example.com' | .host" ==> "'example.com'"

}

0 comments on commit 0e4a812

Please sign in to comment.