搜索
Table_bottom

标签云
Table_bottom

分类
Table_bottom

声明
文章若未特別註明,皆採用 知识共享许可协议 請自覺遵守
Table_bottom

鏈。。。
Table_bottom

存档
Table_bottom

匆匆过客
88548
Table_bottom

功能
Table_bottom

Java的泛型——坑、優秀與缺陷

最近一直在寫一個自己的Android程序(https://github.com/renyuneyun/Easer),所以Java用得比較多。又由於我懶,所以總喜歡讓編譯器做更多,於是想到用泛型來解決之前存在的Object滿地飛又滿地強制類型轉換的情況。然而這時候卻發現,泛型只能解決其中一部分問題,另一部分問題依然存在。

於是起意記錄一下自己知道的、用過的以及碰到的東西,以期有人能給出更加的解決方案(或是乾脆直接指出我錯了最好。。。這樣解決起來最簡單)。

 

一般而言,Java的泛型可以讓程序員寫出一些“形式相同,但具體參數類型不同”的代碼。從字面上說,這一機制在許多語言中都有(如C++的模板),但由於各個語言的實現方式和語義取捨不同,導致具體支持的功能千差萬別。

本文主要集中於Java泛型機制中的坑爹之處。爲了介紹坑爹之處,於是也就需要涉及該機制的理解,同時也會簡單涉及其實現部分。當然,其中一些有意義的地方也會順帶提及(在做對比時)。

继续阅读

Android搞機須知

(應求所作文……其實我更想寫成wiki)

 

雖然看起來每款Android手機都有自己的刷機、root教程,但其實萬變不離其宗,整體上看還是很有規律的。本文從整體上說說Android刷機是什麼、需要做什麼、每個步驟的目的以及效果都是什麼。

继续阅读

直覺上的Hobbs算法

註:文中“(即……)”形式的內容爲輔助理解本質的內容,並非算法內容。

算法分成幾個按順序的部分,每部分如果匹配上,則直接返回,否則往下走。“匹配”的標準爲:agreement等正確,同時滿足當前部分的要求。

整體邏輯/基本想法

算法可大體分爲三個部分:

  1. 在當前句子中尋找(過程較爲複雜,後面詳細說明)
    1. 在目標節點左側進行尋找
    2. 找完還沒找到則在右側進行尋找,但不進入NP和S節點
  2. (如果找不到或沒有合適的)在前面的句子中尋找(如果找不到則繼續向前直到找到爲止)
    • 過程十分簡單:以從左向右、寬度優先爲原則遍歷子樹,尋找匹配的NP

算法過程

算法初始化:從目標代詞(記爲T)所在的NP節點(記爲“當前節點”和/或“X”)開始(即NP->Pron規則中的NP)。

算法唯一循環:

  1. 尋找X之上最近的NP或S節點作爲當前節點,替換原先的X。
  2. 以從左向右、寬度優先爲原則,尋找當前節點X的子樹中(同時在T到X路徑左側)第一個匹配的NP
  3. 若X是S,則看前一個句子的語法樹(見上面)。(只有兩種情況會滿足該要求:
    1. T是句子中(從左往右數)第一個NP(即該句子爲以目標代詞爲主語的句子,或是以目標代詞爲賓語的祈使句等),則首次進入則會遇到該規則
    2. 循環回來遇到S(即尋找完當前句子而沒有找到相匹配的NP)
  4. 尋找X之上最近的NP或S節點作爲當前節點,替換原先的X。
  5. 如果X是NP,而且從T到X的路徑中沒有經過Nominal節點(即T並非X這個NP的定語),則試圖匹配X
  6. 以從左向右、寬度優先爲原則,尋找當前節點X的子樹中(同時在T到X路徑左側)第一個匹配的NP
  7. 如果X是S(即左側已找完),則尋找T到S路徑右側的所有子樹中尋找相匹配的NP。此時如果遇到NP和S,不進入其子樹。
  8. (若如果仍未匹配上)回到3

 

(最近在爲NLP的(高速入門)課準備考試,於是也在看J&M的Speech and Language Processing。其中關於Hobbs的描述看得很頭痛,於是dump一下自己的理解。)

Python中經驗致誤處

豫:這是一篇記述自己學藝不精的文章,而不是介紹什麼奇技淫巧或是隱藏語義的。

 

Python用了也有幾個年頭了(雖然並不是全年都在用),然而發現自己還是有很多依賴(其他語言的)經驗而導致問題的地方。可能是由於自己的學習方式,也可能僅僅是由於語義的問題,這些問題也許是一些人學習中總是會遇到的(嗯,我不會說有一些同學也遇到這些問題),故且總結一下,以饗後人。

 

我個人學習Python所依賴的是:1.其他語言的經驗(Pascal/C/C++/Java);2.實踐;3.《Python學習手冊》。

是的,我沒有看《Python Cookbook》一類的(貌似更適合用來入門的)東西——不是因爲覺得沒必要,而是因爲不知道《Python學習手冊》裏邊的內容居然是那個樣子……而看完《Python學習手冊》以後就再也不想看什麼書了,實在是被它的厚度噁心到了。

 

函數參數默認值

Python中支持函數重載,也(因此而得以)支持參數默認值。

在最初用過的其他語言中,一些(C、Java)不支持重載,而支持的(C++)也沒有內置一些高級數據結構(及其便捷的初始化方法),於是從來沒有遇到過這種問題。

 

到了Python中,我想當然地以爲:參數默認值在每次函數調用的時候都是一個全新的,或者說每次重入的時候都會重新初始化一遍。

而事實上,參數默認值在每次重入時都是同一個!

 

這在簡單一些的數據結構中問題/區別不大,例如數字等不可變類型:因爲它們每次賦值時都會修改引用爲一個新的,而不是修改目標數據的值。

然而,遇到複雜數據結構/對象的時候,區別就體現出來了。我碰到的就是以一個空列表(list)爲默認值時產生的奇妙現象:在函數中每次都要修改這個列表,而由於總是同一個對象,而不是每次從一個空白的新對象開始,於是進行索引、追加等等操作時候結果總是和預期的不同。

 

意識到這個問題之後開始排查問題所在,最終鎖定到參數默認值上。經過一段搜索,搜到了這裏。其中解釋道:參數默認值僅僅在def語句被執行時會被求值。並且,其中也給出了替代的解決方案,如:使用None作爲默認值,之後在函數體中進行判斷。

 

變量作用域

按照C++的習慣,每一個區塊中的變量在出了區塊之後就失效——其中用花括號({})來界定區塊。

故而,在python中我一直以爲每個縮進層級中所創建的變量在出了該層級之後就失效。

然而在教人(之前從沒學過編程)Python時,發現居然不是這樣!當時還鬧了個笑話……

 

所以看來Python中變量作用域是整個函數,而不僅僅是聲明/賦值的那個區塊。

 

import入口

寫的某個flask程序中由於需要在整個程序中共享一些變量/對象,所以在入口的最外區塊中直接進行賦值,然後在其他部分import之。

看起來一直運行正常,然而在假如migrate的時候出事了,數據庫ORM沒有出現。排查好久終於通過id()發現其他部分所用的變量和入口處的那個不同,而它們之間相同……

於是纔意識到,入口的那些代碼在調用的時候執行一次,在import時候又執行一次,而反復import的時候不會重複執行。

是了,以前只知道反復import不會重複執行,但是從來沒意識到入口處並不是import的……

 

 

(主作於2016.3.15。拖延症……)