那就來玩一下吧。
wait to refer:rule
The flip side of this is that you have to deal with old mistakes and with compatibility problems. For example, I consider the C declarator syntax an experiment that failed.-Bjarne Stroustrup, in his SlashDot interview on 2/25/2000.
我嘗試寫成 Haskell 的定義型態。
那個 Type* 能理解就好了 (逃
long *a(int)
1
declare a as function (int) returning pointer to long
1
a :: Int -> Long*
long (*b(int))
1
declare b as function (int) returning pointer to long
1
b :: Int -> Long*
long (*c)(int)
1
declare c as pointer to function (int) returning long
1
c :: (Int -> Long)*
long *d(int)(char)
1
declare d as function (int) returning function (char) returning pointer to long
1
d :: Int -> (Char -> Long*)
long (*e(int))(char)
1
declare e as function (int) returning pointer to function (char) returning long
1
e :: Int -> (Char -> Long)*
long (*f)(int)(char)
1
declare f as pointer to function (int) returning function (char) returning long
1
f :: (Int -> (Char -> Long))*
void qsort(void *, size_t, size_t,int (*)(const void *, const void *))
1
2
3
4
5
6
7declare qsort as function (pointer to void,
size_t,
size_t,
pointer to function (pointer to const void,
pointer to const void)
)
returning int) returning void1
qsort :: Void* -> Size_t -> Size_t -> (Void* -> Void*)* -> Void
start with the identifier
- look to the right for brackets[ ] or parentheses()
- look to the left for asterisks
- remember that parentheses group
- finally, look at the type (eg. int)
重點是先往右讀,然後讀到括號,再往左讀,如此往復。
先找變數宣告名稱,\w+ 後跟的是 ( ,則此宣告為一函數,否則為變數。
先往右,遇到 (
,為函數,參數為 fnArg。
往左讀,遇到 *
,回傳為一指標,指向 long。long *fn(fnArg)
-> fn :: FnArg -> Long*
如果再右邊還有括號,則他的回傳指標為函數指標,其參數為該括號內容。long *fn(fnArg)(argOfAfnRtnedByAFn)
-> fn :: FnArg -> (ArgOfAfnRtnedByAFn -> Long)*
如果後面一直有括號,其指的函數類型就一直向右 eval 括號就好了。long *fn(fnArg)(argOfAfnRtnedByAFn)(argOfAfnRtnedByAFnRtnedByAFn)
-> fn :: FnArg -> (ArgOfAfnRtnedByAFn -> (ArgOfAfnRtnedByAFnRtnedByAFn -> Long*))
注意指標可能出現的位置。long (*fn(fnArg)(argOfAfnRtnedByAFn))(argOfAfnRtnedByAFnRtnedByAFn)
-> fn :: fnArg -> (ArgOfAfnRtnedByAFn -> (ArgOfAfnRtnedByAFnRtnedByAFn -> Long)*)
long (*fn(fnArg))(argOfAfnRtnedByAFn)(argOfAfnRtnedByAFnRtnedByAFn)
-> fn :: fnArg -> (ArgOfAfnRtnedByAFn -> (ArgOfAfnRtnedByAFnRtnedByAFn -> Long))*
有時指標不只一個,看著辦吧。
Illegal combinations include:
- cannot have an array of functions
()() - cannot have a function that returns a function
()[] - cannot have a function that returns an array
所以其實上面五項,應該只有幾個是 Illegal 的(from reference)
其實回傳函數指標和回傳函數在 C 裡是一樣的事情
變數名前有*
代表他是一個指標,long *ptr
-> ptr :: Long*
如果右邊有閉括號,代表他是一個函數指標。long (*ptr)(argOfApointedFn)
-> ptr :: (ArgOfApointedFn -> Long)*
其指的函數類型就一直向右 eval 括號就好了。long (*ptr)(argOfApointedFn)(argOfAFnRtnedByAFnPointedByAPtr)
-> ptr :: (ArgOfApointedFn -> (ArgOfAFnRtnedByAFnPointedByAPtr -> Long))*
一樣,有時指標不只一個,看著辦吧。
我都快搞不清我在寫啥了(
Haskell 的 Type 表達比較好理解(