I do the following
CREATE (p:person { FirstName:"M", LastName: "H" , Language: "en", hash: apoc.util.sha512('1234567','salt')});
Error:
Function call does not provide the required number of arguments: expected 1 got 2.
Function apoc.util.sha512 has signature: apoc.util.sha512(values :: LIST? OF ANY?) :: STRING?
meaning that it expects 1 argument of type LIST? OF ANY?
Description: apoc.util.sha512([values]) | computes the sha512 of the concatenation of all string values of the list (line 2, column 73 (offset: 73))
"CREATE (p:person { FirstName:"M", LastName: "H" , Language: "en", hash: apoc.util.sha512('1234567','salt')});"
what is a Type of List argument?
thanks rob
Have it - i used []
CREATE (p:person { FirstName:"M", LastName: "H" , Language: "de", hash: apoc.util.sha512(["1234567","salt"])});
Related
In this code below :
import Foundation
class Track {
let name : String
let instructor : String
init(name : String, instructor : String) {
self.name = name
self.instructor = instructor
}
}
class Student {
let name : String
init(name : String) {
self.name = name
}
}
let tracks = [
Track(name: "Mobile", instructor: "Bob"),
Track(name: "Web", instructor: "Kevin"),
Track(name: "Games", instructor: "May")
]
let students = [
Student(name: "Harry Potter"),
Student(name: "Hermoine Granger"),
Student(name: "Draco Malfoy")
]
var assignments : [String : Track] = [:]
for count in students {
print(count.name)
var temp = count.name
assignments[temp] = tracks[0].instructor
}
print(assignments)
An error code occurs on this line
assignments[temp] = tracks[0].instructor
And it says this:
Cannot assign value of type 'String' to subscript of type 'Track'
I have tried multiple things such as putting tracks[0].instructor in a variable and then putting that in the line of code instead but it doesn't resolve the issue. Help would be appreciated. Thank you!
assignments is a dictionary ([String:Track])
assignment["yourKey"], it's type of Track, you can not assign type of String to it.
I can not understand why you want to use a dictionary!!
if you want to use dictionary change assignments:[String:Track] to assignments:[String:String]
Solved
For a first ever macro to write this wasnt the easiest. But I learned a lot, much kudo's to Gama11 who pointed me in the right direction, and the coreteam for such a thing of beauty: Haxe.
And I even added some slick doc field strings, so you get nice info during autocompletion.
Main.hx
var e1:Either<String, Int, Bool> = Either3._1('test');
var e2:Either<String, Int, Bool> = Either3._2(1);
var e3:Either<String, Int, Bool> = Either3._3(true);
var error:Either<String, Int, Bool> = Either3._3('Bool expected, but got a String this will give an error');
Either.hx
package;
#:genericBuild(EitherMacro.build())
class Either<Rest> {}
/*#:genericbuild only works on classes, but
can still override the class with an enum. Funky. */
EitherMacro.hx
package;
#if macro
import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.Type;
using haxe.macro.Tools;
class EitherMacro {
static var eitherTypes = new Map<Int,Bool>();
static function build():ComplexType {
return switch (Context.getLocalType()) {
case TInst(_.get() => {name: "Either"}, params):
buildEitherEnum(params);
default:
throw false;
}
return macro:Dynamic;
}
static function buildEitherEnum(params:Array<Type>):ComplexType {
var numParams = params.length;
var name='Either$numParams';
if (!eitherTypes.exists(numParams)){
Context.defineType(defineType(name, params));
eitherTypes[numParams] = true;
}
return TPath({pack: [], name: name, params: [for (t in params) TPType(t.toComplexType())]});
}
private static inline function defineType(name:String, params:Array<Type>){
var typeParams:Array<TypeParamDecl> = [];
var typeStrings:Array<String>=[];
var numParams = params.length;
var fields:Array<Field>=[];
for (i in 0...numParams) {
var t=i+1;
typeStrings.push(params[i].toString());
}
var constDocStr=typeStrings.join(',');
for (i in 0...numParams) {
var t=i+1;
var typeString:String=typeStrings[i];
typeParams.push({name:'T$t'});
fields.push(
{
name: '_$t',
pos: Context.currentPos(),
doc: 'from $name<$constDocStr> _$t(v: $typeString)',
kind:FFun({
ret: null,
params: [{name:'T$t'}],
expr: null,
args: [
{
name: 'v',
type: TPath(
{
name:'T$t',
params:[],
pack:[]
}
)
}
]
}
)
}
);
}
var docStr:String="Either represents values which are either of type ";
for(k in 0...typeStrings.length){
if(k!=typeStrings.length-1){
docStr+=typeStrings[k]+" or ";
} else {
docStr+=typeStrings[k]+".";
}
}
return {
pack:[],
name:name,
pos:Context.currentPos(),
doc:docStr,
isExtern: false,
meta:null,
kind:TDEnum,
fields:fields,
params:typeParams
}
}
}
#end
Debugging your macro's the easy way
usage of -D dump=pretty dumps typed AST in dump subdirectory using prettified mode. The output from dump=pretty is almost indistuingishable from regular Haxe code. When errors appear, you find iin the root of the dump directory a file called 'decoding_error.txt'. Its contents might look like this:
{
doc: null
fields: null <- expected value
isExtern: null
kind: null <- expected value
meta: null
name: null <- expected value
pack: null <- expected value
params: null
pos: null <- expected value
}
line 3: expected value
line 5: expected value
line 7: expected value
line 8: expected value
line 10: expected value
This made it much easier for me to debug. But the even better way, is way simple... To debug the easiest way, go to your macrofile (in my case EitherMacro.hx) and do
class EitherMacro{
public static function build(){
var fields=Context.getBuildFields();
var type=Context.getLocalType();
trace(type);
for(f in fields){
trace(f);
}
// your other code
/*
If you use #:build)() instead of #:genericbuild
to debug. Make sure the buildfunction returns
Array<Field> and put at the last line
return Context.getBuildFields();
if you use #:genericbuild you must return
ComplexType, and you can add as the line
return macro:Dynamic; if you have no working return yet.
*/
}
}
the output might look like this:
source/EnumBuilder2.hx:18: TEnum(SomeEnum,[TInst(SomeEnum.T1,[]),TInst(SomeEnum.T2,[]),TInst(SomeEnum.T3,[])])
source/EnumBuilder2.hx:20: {name: _1, doc: null, pos: #pos(source/SomeEnum.hx:4: characters 5-14), access: [], kind: FFun({ret: null, params: [], expr: null, args: [{name: v, opt: false, meta: [], type: TPath(<...>), name_pos: #pos((unknown)), value: null}]}), meta: [], name_pos: #pos(source/SomeEnum.hx:4: characters 5-7)}
source/EnumBuilder2.hx:20: {name: _2, doc: null, pos: #pos(source/SomeEnum.hx:5: characters 5-14), access: [], kind: FFun({ret: null, params: [], expr: null, args: [{name: v, opt: false, meta: [], type: TPath(<...>), name_pos: #pos((unknown)), value: null}]}), meta: [], name_pos: #pos(source/SomeEnum.hx:5: characters 5-7)}
source/EnumBuilder2.hx:20: {name: _3, doc: null, pos: #pos(source/SomeEnum.hx:6: characters 5-14), access: [], kind: FFun({ret: null, params: [], expr: null, args: [{name: v, opt: false, meta: [], type: TPath(<...>), name_pos: #pos((unknown)), value: null}]}), meta: [], name_pos: #pos(source/SomeEnum.hx:6: characters 5-7)}
Another good idea with #:genericbuild(), is to first constructed an enum by hand(or whatever type) and after that trace it using a #:genericbuild, or if you got too much errors using #:build. Then you can copy those trace outputs and try use that code to craft the AST in the macro. This will seriously speedup your development, especially in case of complicated macro's. Almost mindlessly ;-)
Your macro has never run.
Replace your build() function with the following to verify
static function build():ComplexType {
trace('build');
return macro:Dynamic;
}
I suppose #:genericBuild only works for class
My code was supporting Swift 3.3 before, now I'm upgrading it to Swift 4.1 using Xcode 9.3. It shows me the following error while trying to build my project.
Here is code for JSON parsing
// MARK: Store JSON initializer
convenience init?(withJSON json: JSON) {
//json mapping
//This is of type [Character] after mapping
let services = json["services"].arrayValue.flatMap({ $0 }).flatMap({ $0.1.stringValue }) //Convert response to 1D array and convert it to array if String
}
Here is that init method which I'm trying to call
//Custom init method
init(id: Int, storeNumber: String, title: String, location: Location, type: String, zip: String, parent: Int, city: String, services: [String], state: String, storePhone: [String], pharmacyPhone: [String], pharmacyFax: [String], workingHours: WorkingHoursString) {
//field with error
//here self.services is of type [String]
self.services = services
}
I'm using
pod 'SwiftyJSON', '3.1.4' For Json parsing.
Error - Cannot convert value of type '[character]' to expected argument
type '[String]'
/* JSON for services is as given
"services":[
[
"Fresh Food"
]
]
*/
print("Services are \(services)")
Services are ["F", "r", "e", "s", "h", " ", "F", "o", "o", "d"]
What could be the simplest solution to fix this?
The same behavior can be observed in the following code:
let services: [[String: Any]?] = [
["service1": "service1-name"],
["service2": "service2-name"]
]
let result = services
.flatMap({ $0 })
.flatMap({ $0.1 as! String })
print(result)
I think this is caused by the multiple changes in String and Dictionary in Swift 4 (String becoming a Collection of characters for example). In the code above the first flatMap merges (flattens) the dictionaries into one dictionary and the second flatMap takes every value as a String and flattens them as a 2D Collection of Character.
I think you want something like this:
let result = services
.compactMap { $0 } // remove nil dictionaries
.flatMap { // take all dictionary values as strings and flatten them to an array
$0.values.map { $0.stringValue }
}
print(result)
This line gives an array of strings, expected results
let services = json["services"]
.arrayValue
.flatMap { $0.arrayValue }
.map { $0.stringValue }
The title almost says it all. My project is in Swift 2.3. Ocassionaly a custom struct model object is introduced. For various reasons, this must conform to Equatable.
Let's for example have a struct with 6 different value-type variables, all from Swift standard library.
struct Address: Equatable {
let firstName: String
let lastName: String
let street: String
let streetNumber: Int
let city: String
let countryCode: Int
}
func ==(lhs: Address, rhs: Address) -> Bool {
return (
lhs.firstName == rhs.firstName &&
lhs.lastName == rhs.lastName &&
lhs.street == rhs.street &&
lhs.streetNumber == rhs.streetNumber &&
lhs.city == rhs.city &&
lhs.countryCode == rhs.countryCode)
}
What is the correct algorithm to ensure I will test ALL the combinations of (in)equality in my unit test?
Permutations/combinations? Perhaps something more programatic?
In this case, exhaustively testing all the combinations is just a flat-out poor strategy. It's unnecessary, and serves only to make unit testing more troublesome and makes you less likely to do it well.
With a very simple equality function like this, there's a good case to be made that you don't need to test it at all. If you must test it, testing one case for equality, and one case for inequality, is good enough. If you want to really go crazy, you can have one test for equality, and six tests for inequality in each of your members.
It's better to write out the test cases individually and manually, because you should be able to have faith in the correctness of a unit test simply by looking at it. If you can't, then you can end up in the rather absurd position of having to unit test your unit tests.
However, if you really absolutely insist on doing things the wrong way and exhaustively testing every possible combination, then you can do so like this:
func makeAddressPair(sames: [Bool]) -> (Address, Address) {
let firstName = ["John", sames[0] ? "John" : "Jane"]
let secondName = ["Smith", sames[1] ? "Smith" : "Williams"]
let street = ["Acacia Avenue", sames[2] ? "Acacia Avenue" : "Privet Close"]
let streetNumber = [10, sames[3] ? 10 : 21]
let city = ["Leeds", sames[4] ? "Leeds" : "Bolton"]
let country = [1, sames[5] ? 1 : 2]
return (Address(firstName: firstName[0], lastName: secondName[0], street: street[0],
streetNumber: streetNumber[0], city: city[0], countryCode: country[0]),
Address(firstName: firstName[1], lastName: secondName[1], street: street[1],
streetNumber: streetNumber[1], city: city[1], countryCode: country[1]))
}
class AddressCompareTests: XCTestCase {
func testAddressCompare() {
var comparesEqual = 0
var comparesInequal = 0
for a in [true, false] {
for b in [true, false] {
for c in [true, false] {
for d in [true, false] {
for e in [true, false] {
for f in [true, false] {
let (first, second) = makeAddressPair(sames: [a, b, c, d, e, f])
if first == second {
comparesEqual += 1
}
else {
comparesInequal += 1
}
}
}
}
}
}
}
XCTAssertEqual(comparesEqual, 1)
XCTAssertEqual(comparesInequal, 63)
}
}
You have 2 ^ 6 = 64 possible combinations, because you have six members, and between two structs, each pair of members can be either equal, or not equal. Here we have a helper function to generate a pair of structs based on a list of which members should be equal between them, and a nested loop to generate all possible combinations of pairs. When you compare all the pairs, exactly one should compare equal, and exactly 63 should compare unequal, so those are the test conditions we assert, since at least then we have some kind of poor cousin to quality control over the correctness of our test.
If instead you tested two or seven cases manually, it would be much simpler, clearer, easier to read and verify, and would take fewer lines of code, than doing it this way.
I'm a relative newbie on TDD but this what I have learned so far:
Helper function
func performNotEqualTestWithAddresssProperties(firstNameF: String, firstNameS: String, LastNameF: String, LastNameS: String, streetF: String, streetS: String streetNumberF: Int, streetNumberS: Int, cityF: String, cityS: String, countryCodeF : Int, countryCodeS : Int){
let AddressFirst = Address(firstName: firstNameF, LastName:LastNameF, street: streetF, streetNumber: streetNumberF, city : cityF, countryCode: countryCodeF)
let AddressSecond = Address(firstName: firstNameS, LastName:LastNameS, street: streetS, streetNumber: streetNumberS, city : cityS, countryCode: countryCodeS)
XCTAssertNotEqual(AddressFirst, AddressSecond, "Addresses are not equal")
// 'F' means first, 'S' means second, I just avoided to not have long lines
// The helper function takes 2 sets of Addresses and Asserts if they ARE equal
}
actual test
func testWhenAddressDiffers_SHouldNotBeEqual() {
performNotEqualTestWithAddresssProperties(firstNameF: "Earl", firstNameS: "Earl", LastNameF: "Grey", LastNameS: "Grey", streetF: "south", streetS: "south", streetNumberF: 23, streetNumberS: 23, cityF: "silicon valley", cityS: "silicon valley", countryCodeF: 24, countryCodeS: 29)
//write another and switch firstName,another and switch LastName, ...
Here I only tested countryCode. All other elements were the same.
to fully test your Address struct equality, each time you populate all properties of Address identical except for one. So basically you have to write this function 6 times.
You have 6 equalities to test. They are independent expressions and need to be treated independently. This is the best programmatic way I know of.
I'm having trouble coding an apparently simple task. I want to add new client profile data to a client profile dictionary (clientDatabase) but keep getting errors - can't seem to append - error: value of type '(String: clientProfile)' has no member 'append' (see error at bottom of code)
Any insights you can provide are greatly appreciated.
Thanks,
Bill
//: Playground - noun: a place where people can play
import UIKit
import Foundation
/*
code copied from B-C Dev Database - structs but simplified with fewer variables
goal is to getappend new client to work.
*/
/*
Globals: these go in main.swift file
*/
struct clientProfile {
var firstName: String = ""
var lastName: String = ""
var group: Int = 0
}
//var clientDatabase : NSMutableDictionary! = [String:clientProfile]()
var clientDatabase:[String:clientProfile]
/* sample data template: phone is key, sub array is;
(firstName: "", lastName: "",pilatesGroup: )
*/
clientDatabase = [
"1234567": clientProfile(firstName: "Sally", lastName: "Sillious", group: 3),
"2345678": clientProfile(firstName: "Sue", lastName: "Parker",group: 8),
"3456789": clientProfile(firstName: "Bob", lastName: "Parker", group: 2),
"5678901": clientProfile(firstName: "Jim", lastName: "Beam", group: 12)
]
clientDatabase.count
// so far so good
/*
add new client
declare local variables in scene swift files where used
*/
var firstName: String = ""
var phone:String = ""
var newPhone: String = ""
var newFirstName: String = ""
var newLastName: String = ""
var newGroup: Int = 0
// define struct using these input variables for values but with same keys as (global) clientDatabase
struct newClientProfile {
var firstName: String = newFirstName
var lastName: String = newLastName
var group: Int = newGroup
}
// put newClientProfile into newClientDictionary
var newClientDatabase:Dictionary = [String:newClientProfile]()
// input values from scene - UITextFields
newPhone = "4567890"
newFirstName = "Super"
newLastName = "Dave"
newGroup = 14
// test that all values are where they should be
clientDatabase
clientDatabase.count
newClientDatabase = [newPhone:newClientProfile()]
newClientDatabase.count
// ok so far
//the following line returns an error
clientDatabase.append(newClientDatabase)
// can't seem to append - error value of type '(String: clientProfile)' has no member 'append'
Two things. First of all clientDatabase is a dictionary which doesn't have append, instead you'll have to iterate through the other dictionary and insert its elements into clientDatabase.
The other issue is that clientDatabase and newClientDatabase aren't the same type. The first one is [String : clientProfile] and the second is [String : newClientProfile]. You'll have to convert the values from one type to the other to combine the dictionaries.
Looking deeper into the code there some misunderstandings about the language. For example:
struct newClientProfile {
var firstName: String = newFirstName
var lastName: String = newLastName
var group: Int = newGroup
}
// put newClientProfile into newClientDictionary
var newClientDatabase:Dictionary = [String:newClientProfile]()
You're creating a struct just for the purpose of containing a single set of values when you already have clientProfile. Instead you could do:
var newClientProfile = clientProfile(firstName: newFirstName, lastName: newLastName, group: newGroup)
This will create a variable which is an instance of clientProfile and stores the information you want. However, you have the other variables defined as empty values.
Here's a cleaned up version of your code, take a look at it and let me know if you have any questions.
struct ClientProfile { // Convention is to use initial caps for enum, struct, class
let firstName: String
let lastName: String
let group: Int
}
var clientDatabase = [
"1234567": ClientProfile(firstName: "Sally", lastName: "Sillious", group: 3),
"2345678": ClientProfile(firstName: "Sue", lastName: "Parker",group: 8),
"3456789": ClientProfile(firstName: "Bob", lastName: "Parker", group: 2),
"5678901": ClientProfile(firstName: "Jim", lastName: "Beam", group: 12)
]
// input values from scene - UITextFields
let newPhone = "4567890"
let newFirstName = "Super"
let newLastName = "Dave"
let newGroup = 14
// define struct using these input variables for values but with same keys as (global) clientDatabase
let newClientProfile = ClientProfile(firstName: newFirstName, lastName: newLastName, group: newGroup)
let newClientDatabase = [newPhone:newClientProfile]
for (phone,client) in newClientDatabase {
clientDatabase[phone] = client
}