OCaml functional update with nested record - ocaml

Is there a way, possibly using a ppx extension or similar, to use the functional update syntax { record with key = value } with a nested record?
For instance, in the following example program I'm functionally updating only the outermost record, when I really want to target an "inner" one.
type outer = {
a : float;
b : inner
}
and inner = {
c : float;
}
let item = { a = 0.4; b = { c = 0.7 } }
let () = ignore { item with b = { c = 0.8 }
It becomes less convenient if inner has more than one field.
I'd like to be able to write something like the following (strawman syntax):
let () = ignore { item with b.c = 0.8 }

You can write this in straight OCaml:
{ item with b = { item.b with c = 0.8 } }
I assume you're using ignore just for the examples; it doesn't make sense to ignore the result of a functional record update.

Related

EMF: Defining a generic containment reference in an Ecore metamodel

It is a long time since I have used EMF and I am stuck on this.
I would like to create a generic type equivalent to:
class Result<T:ASTNode>{
T root;
}
I am defining this in Kotlin:
val result = ePackage.createEClass("Result").apply {
// I think this part is correct
val typeParameter = EcoreFactory.eINSTANCE.createETypeParameter().apply {
this.name = "T"
this.eBounds.add(EcoreFactory.eINSTANCE.createEGenericType().apply {
// astNode is my EClass
this.eClassifier = astNode
})
}
this.eTypeParameters.add(typeParameter)
val rootContainment = EcoreFactory.eINSTANCE.createEReference()
rootContainment.name = "root"
// STUCK!
// here should I set rootContainment.eType? rootContainment.eGenericType?
// how?
rootContainment.isContainment = true
rootContainment.lowerBound = 0
rootContainment.upperBound = 1
this.eStructuralFeatures.add(rootContainment)
addContainment("issues", issue, 0, -1)
}
The equivalent .ecore is :
<eClassifiers xsi:type="ecore:EClass" name="Result">
<eTypeParameters name="T">
<eBounds eClassifier="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
</eTypeParameters>
<eStructuralFeatures xsi:type="ecore:EReference" name="t">
<eGenericType eTypeParameter="#//Result/T"/>
</eStructuralFeatures>
so you want to use rootContainment.eGenericType with a new EGenericType that references your ETypeParameter

Dart print multiple list item at once

How can I type something like "print(list[1,4]);" in Dart?
For example:
int main() {
var products = new List(5);
products[0] = "Laptop";
products[1] = "Mouse";
products[2] = "Keyboard";
products[3] = "Monitor";
products[4] = "Microphone";
print(products[1]); // Mouse
print(products[1,3]); // I want to see 'Mouse,Monitor'
}
This is not directly supported in the SDK but you can easily make a extension on e.g. List to add this feature:
void main() {
final products = List<String>(5);
products[0] = "Laptop";
products[1] = "Mouse";
products[2] = "Keyboard";
products[3] = "Monitor";
products[4] = "Microphone";
print(products[1]); // Mouse
print(products.selectMultiple([1,3]).join(',')); // Mouse,Monitor
}
extension MultiSelectListExtension<E> on List<E> {
Iterable<E> selectMultiple(Iterable<int> indexes) sync* {
for (final index in indexes) {
yield this[index];
}
}
}
You can't make it so [1,3] (as in you own example) would be valid since the [] operator does only allow one argument. So instead, we need to make a method which takes our requested indexes as argument.

Scala function takes 2 hours with 2 million values

Would be grateful if any ideas to speed it up!
case class Pair(aa:String, bb:String)
case class OutputRow(bb:String, aa:String, bb_2:String, aa_2:String)
def startSearch(
_1_sorted: Array[Pair] ,
_2_hashmap: HashMap[String, String] ) : ArrayBuffer[OutputRow] = {
var outputTableListBuffer = ArrayBuffer[OutputRow]()
var searchComparisionFlag = false
var storeMain = Pair("0","0") //Initialize with Dummy data
var i = 0
def search(xxxx_1: Pair): Unit = {
if (searchComparisionFlag==true) {
var _2_exists = _2_hashmap.exists(_._1 == xxxx_1.aa)
if (_2_exists) {
val _2_xxxx = _2_hashmap(xxxx_1.aa)
outputTableListBuffer.append(OutputRow(storeMain.aa, storeMain.bb,_2_xxxx, xxxx_1.aa))
i = i + 1
if (i % 1000 == 0) println("In recursive search storeMain: ", storeMain)
var storePair = Pair(_2_xxxx,xxxx_1.aa)
search(storePair)
} else {
searchComparisionFlag = false
return
}
} else {
var _2_exists = _2_hashmap.exists(_._1 == xxxx_1.aa)
if (_2_exists) {
val _2_xxxx = _2_hashmap(xxxx_1.aa)
searchComparisionFlag = true
outputTableListBuffer.append(OutputRow(xxxx_1.aa, xxxx_1.bb,_2_xxxx, xxxx_1.aa))
var store = Pair(_2_xxxx,xxxx_1.aa)
search(store)
}
}
}
_1_sorted.foreach{ aa_1 =>
val store = Pair(aa_1.aa, aa_1.bb)
storeMain = store
search(store)
}
outputTableListBuffer
}
The above function takes 2 hours with 1 million values in _1_sorted and with a good 1 Million lookup in the hashmap.
Any ideas to speed this up?
This is a recursive logic function
The biggest problem is this:
_2_hashmap.exists(_._1 == xxxx_1.aa)
This is checking every single element of the hashmap on every call. Instead, use get:
_2_hashmap.get(xxxx_1.aa) match {
Some(_2_xxxx) => // Found
???
None => // Not found
???
}
Other code issues:
Don't use return
Pass flags down through recursive call rather than using global var
Use val wherever possible
Don't start variable names with _

Convert a string into closure in ColdFusion

I have a very basic question. Is it possible to convert a string into a closure? I tried evaluate() but it didn't work.
evaluate( "myFunction = function(val){ return dollarFormat( val ); }" );
What I have in mind is to save custom functions in the database as string and then run it as needed.
Thank you!
Edit: Just to clarify: I want to be able to save "function(val){ return dollarFormat( val ); }" as a string in database and be able to convert it into a functioning closure.
I would go with user2943775 answer:
<cfscript>
FileWrite("/ram/UDFs.cfm", "<cfset myFunction = function(val){ return dollarFormat( val ); }>")
include template="/ram/UDFs.cfm";
writedump(myFunction(10));
</cfscript>
And in your Application.cfc
component {
this.mappings["/ram"] = "ram://";
...
}
I came across a similar solution, though I was unable to use the in-memory filesystem due to security restrictions. In my Application.cfc, I added the following mapping:
this.mappings = {
"/models" = "#APP_ROOT_PATH#cfcs/models",
"/utils" = "#APP_ROOT_PATH#cfcs/utils",
"/modules" = "#APP_ROOT_PATH#_modules",
"/components" = "#APP_ROOT_PATH#cfcs",
"/udfs" = "#APP_ROOT_PATH#includes/udfs" // path for global (and temporary) UDFs
};
The UDF I created is as follows:
/**
* Takes a string representation of a function and returns it as a Closure
* #output false
* #return Closure
*/
private any function toClosure (required string closure) {
local.id = replace(createUUID(), "-", "", "all");
local.udfpath = "/udfs/udf#id#.cfm";
local.script = "<cfscript>local.fn#id# = #closure#;</cfscript>";
try {
fileWrite(expandPath(udfPath), script);
include udfpath;
} catch (any e) {
} finally {
try {
fileDelete(expandPath(udfPath));
} catch (any e) {}
}
if (!structkeyExists(local, "fn#id#") || !isClosure(local["fn#id#"])) {
throw (message="Unable to compile closure");
}
// return the closure
return local["fn#id#"];
}
And the result:
myFn = toClosure("function (num) { return num + 1; }");
myFn(1); // returns 2

How to combine/define two variables in 1?

i'd like to "define" 2 variables as 1 new variable, which then contains the contents/data of both previous variables.
Let's say the first variable is called 'var A' and the second 'var B',
can i combine those 2 in a new variable simply like this?
var ALL = var A + var B;
..or how is the correct syntax for this?
I hope this isn't too abstract? ;)
var A and B are both variables defining external geojson files, and I'd like to be able to "combine" these 2 in 1 new variable.
I would recommend using a function to handle combining them.
function combine(A,B) {
var C = {};
C.stuff_from_A = A.some_info;
C.stuff_from_B = B.some_info;
return C;
}
now you can perform what you ask.
var C = combine(A,B);
EDIT:
An example involving location data:
function combine(A,B) {
var C = {};
C.position_of_A = A.coordinate_info;
C.position_of_B = B.coordinate_info;
return C;
}
or to store the midpoint between them:
function combine(A,B) {
var C = {};
C.midpoint = average(A.location,B.location);
return C;
}
or more generally:
function combine() {
var C = {}; // Initialize
// Logic to combine and store info
return C; // Return the new object
}
EDIT 2
C.totalMarkers = [];
for (var i = 0; i < numberOfMarkersInA; i++) {
C.push(A.getMarker(i));
}
for (var i = 0; i < numberOfMarkersInB; i++) {
C.push(B.getMarker(i));
}
That is pseudo-code, those variable names will need to changed of course.
If there are the objects - serialize they and add with separator. If there is simple string, number, bool or something else, add with separator directly.
Sounds like you want to merge 2 geojson files into one. According to this answer, the concat method should do it for you:
var finalObj = json1.concat(json2); // Merge the 2 files together.