Using typedef enum as a new type - typedef

I got a beginner question and I've surfed through the Internet and only find definition like
typedef enum
{
A,B,C,D
}CAP;
CAP a=A; // printf("%d",a); => 1
But my question is (from Stanford CS107 section handout ) that :
typedef enum {
Integer, String, List, Nil
} nodeType;
// skip
char *ConcatAll(nodeType *list)
{
switch (*list) {
case Integer:
case Nil: return strdup("");
case String: return strdup((char *)(list + 1));
}
nodeType **lists = (nodeType **)(list + 1);
// skip after
}
Since the nodeType is numeric (1 , 2, 3), how come it could be used as type declaration
nodeType *list;
and even this?
nodeType **lists = (nodeType **)(list + 1);
Or maybe there's a manual so I can find? Thank you for your kind advice!

When you define a type with typedef, you can use it wherever a type can be used. It's treated as if you'd used the type that was defined. So:
nodeType *list;
is equivalent to:
enum {Integer, String, List, Nil} *list;

Related

Get value of enum type in swift

I'm trying to get a default value for the enum so I can use it as a param. This code isn't working, but I'd like to get something like:
print("Param: \(Params.RCLoss.description)")
and the output should be:
Param: RC_LOSS_MAN
Here is the code:
enum Params {
enum RCLoss: Int32, CustomStringConvertible {
case disable = 0
case enable = 1
var description: String {
return "RC_LOSS_MAN"
}
}
}
I want to be able to pass this:
set(parameterType: Params.RCLoss.description, parameterValue: Params.RCLoss.enable)
which should correspond to these values being set:
set(parameterType: "RC_LOSS_MAN", parameterValue: 0)
It seems you want just
enum rcLoss: Int32 {
case disable = 0
case enable = 1
static var description: String {
return "RC_LOSS_MAN"
}
}
rcLoss is a type, description has to be static for you to be able to call rcLoss.description. And that means you cannot use CustomStringConvertible. You would use CustomStringConvertible to convert enum values to a String.
From Swift Book - Enumerations:
You access the raw value of an enumeration case with its rawValue property.
set(parameterType: Params.rcLoss.description, parameterValue: Params.rcLoss.enable.rawValue)
If you can though I would use the enumeration as the type of the formal parameter so that someone can't pass an invalid value to that function. Also I'm assuming that there is a reason you have nested an enum inside of an otherwise empty enum...

Type of expression is ambiguous without more context, while using enums

So I have the following enum
enum Franchise: String {
case visa = "vi"
case mastercard = "mc"
case americanexpress = "ax"
case diners = "di"
}
Then with an object that has a franchise attribute declared as follows
var franchise : String?
Somewhere in my code I verify the following with
if(paymentCard.franchise! == .visa) {
self.franchiseLogo.image = UIImage(named: "american_express_icon")
}
And I get an "Type of expression is ambiguous without more context" error.
Also I have tried doing the same with an switch case statement.
switch self.paymentCard.franchise {
case (.visa):
// Something
case (.mastercard):
// Something
case (.americanexpress):
// Something
case (.diners):
// Something
}
But in each case I get an error saying "Enum case 'visa' not found in type 'String'"
You have declared franchise as an optional String and you´re trying to match it against the Enum type Franchise which will cause a missmatch.
You can either change the type of your variable from:
var franchise : String?
To:
var franchise : Franchise
And use your current code. If you still want to use String? on your variable franchise, then you need to update your code to the following:
if franchise == Franchise.visa.rawValue {
}
switch franchise! {
case (Franchise.visa.rawValue):
// Something
case (Franchise.mastercard.rawValue):
// Something
case (Franchise.americanexpress.rawValue):
// Something
case (Franchise.diners.rawValue):
// Something
default:
break
}
So what has changed is that you´re matching your string variables against the rawValue of Franchise.
There is a type mismatch String vs. Franchise.
Although the raw value is String the type of the enum is Franchise.
There are (at least) 3 solutions:
Check on the raw value (no parentheses around the if condition)
if paymentCard.franchise! == Franchise.visa.rawValue {
Create a Franchise instance from the raw value
if Franchise(rawValue: paymentCard.franchise!)! == .visa {
Declare franchise as Franchise and change the related code respetively
var franchise : Franchise?
And no parentheses around cases, too ! - case .visa:

How to convert a Swift array to a tuple in a single line? [duplicate]

I just want to convert an array into a tuple in Swift; something like the following:
>>> myArray = [1,2,3,4,5]
>>> mytuple = tuple(myArray)
>>> mytuple
(1, 2, 3, 4, 5)
What's the easiest way of doing that?
(I only started learning Swift today, so I am very, very new).
It's actually quite possible, if you are willing to do some low level magic. I don't think it works if the tuple has a collection type, though. This is mainly for interacting with C libraries.
typealias TupleType = (UInt8, UInt8, UInt8)
var array = [2, 3, 4] as [UInt8]
var tuple = UnsafeMutablePointer<StepsType>(malloc(UInt(sizeof(TupleType))))
memcpy(tuple, array, UInt(array.count))
More of this stuff can be found here:
https://codereview.stackexchange.com/questions/84476/array-to-tuple-in-swift/84528#84528
Because 70% of us are highly visual beings:
You can't do this because the size of a tuple is part of its type, and this isn't true for an array. If you know the array's length, you can just do let myTuple = (myArray[0], myArray[1], ...). Or you can build your architecture around tuples from the beginning. What are you trying to do?
This is a common problem which occurs in lots of other languages. See How do I convert a list to a tuple in Haskell?
if what you want to do is extract multiple value from array at the same time, maybe
the following code could help you
extension Array {
func splat() -> (Element,Element) {
return (self[0],self[1])
}
func splat() -> (Element,Element,Element) {
return (self[0],self[1],self[2])
}
func splat() -> (Element,Element,Element,Element) {
return (self[0],self[1],self[2],self[3])
}
func splat() -> (Element,Element,Element,Element,Element) {
return (self[0],self[1],self[2],self[3],self[4])
}
}
then you can use it like this
let (first,_,third) = ( 0..<20 ).map { $0 }.splat()
you can even write a codegen to generate the extension code
This my universal solution for copy array data to tuple. The only problem that I could not solve is to check the type of the element in the tuple and the element from the array.
/// Unsafe copy array to tuple
func unsafeCopyToTuple<ElementType, Tuple>(array: inout Array<ElementType>, to tuple: inout Tuple) {
withUnsafeMutablePointer(to: &tuple) { pointer in
let bound = pointer.withMemoryRebound(to: ElementType.self, capacity: array.count) { $0 }
array.enumerated().forEach { (bound + $0.offset).pointee = $0.element }
}
}
Scared of unsafe pointers? Or need support for tuples with different types inside?
It can also be done like this:
public extension Array {
public var tuple: Any? {
switch count {
case 0:
return ()
case 1:
return (self[0])
case 2:
return (self[0], self[1])
case 3:
return (self[0], self[1], self[2])
case 4:
return (self[0], self[1], self[2], self[3])
case 5:
return (self[0], self[1], self[2], self[3], self[4])
default:
return nil
}
}
Because typing this out can be a little error prone, it's a good idea to write tests for this that make sure the right tuple is returned.
I've used this approach in ArrayPlusTuple.
So instead of writing this functionality yourself you could just add pod 'ArrayPlusTuple' to your pod file and get this tested functionality for free.

Adding value to Swift dictionary with enum key

I defined Dictionary in Swift, with enum as the key and struct as value. At runtime I want to add value to the dictionary for a given enum key, however I get the following error:
'#lvalue $T9' is not identical to '(MyEnum, MyData)'
enum MyEnum {
case A, B, C
}
struct MyData {
var x : Int
var y : Int
init(x:Int, y: Int) {
self.x = x
self.y = y
}
}
class Tester {
let myDictionary = [MyEnum : MyData]()
func dummy() {
self.myDictionary[MyEnum.A] = MyData(x: 1, y: 2) // <-- error in this line
}
}
Any idea how to do it properly ?
The problem is that you’ve declared myDictionary with let rather than var. Switch it to var and your code will work as expected.
Dictionaries are structs, which are a “value” type. That means when you declare them with let, they are frozen forever with the value they were assigned. You can’t call methods that change their value, including assigning to them via a subscript ([ ]).
Unfortunately the error message isn’t super-helpful. Ideally it would read something like “attempt to modify immutable value myDictionary”.
Don’t let this put you off using let though – it’s a great practice to use let by default unless you know you need to change a value. But in this instance you do, so you need to use var.

Should a const member function return a const or non-const?

struct Type
{
auto opBinary(string op)(Type other) const {
return Type(); // #1 return type is Type
return typeof(this)(); // #2 return type is const(Type)
}
}
unittest
{
Type t1, t2;
auto t3 = t1 + t2;
}
In t1.opBinary!("+")(t2), t1 becomes a const, while t2 stays non-const. Should opBinary's return type be Type or const(Type), and why?
const(T) is a supertype, so maybe it should return a const, but I've hardly seen this in practice. Things also become rather complicated when dealing with a hierarchy of types and functions that use those types or are used by those types.
Since the return value here is a new object, I'd say make it non-const. Being new, it can be modified safely, so no reason to unnecessarily restrict it with const.
If you were returning a part of the existing object, you'll want to use inout instead of const. inout means the constness of the object will also go to the return value.
inout(Type) opBinary(string op)(Type other) inout {
return whatever;
}
Now if you use a const(Type) object, the return will be const as well, and if it is called on a mutable object, the return is also mutable.
Should return type be T or const(T)? Any will do.
Which one is better? Depends on your intended behavior.
const qualifier on opBinary only means that hidden "this" argument is const. Nothing more, nothing else. It does not imply anything about the return type. It all boils down to pretty simple choice:
struct Type
{
int a;
auto opBinary(string op)(Type other) const
if (op == "+")
{
return Type(this.a + other.a);
}
}
void main()
{
Type first, second;
(first + second).a = 42; // Do you want to allow this?
// Yes -> return non-const
// No -> return const
}
If you want to preserve qualifiers of arguments, use either inout (see Adams answer) or manual check for qualifiers for more complicated choices.
With either choice remember automatic type deduction:
auto third = first + second;
third.a = 42; // Error if returns const
Type fourth = first + second;
fourth.a = 42; // Fine in both cases, struct was copied
In the end it is about you intention as a type designer how class/struct should behave.