SlideShare una empresa de Scribd logo
1 de 37
(do “Concurrency in Clojure”) (by (and  “Alex” “Nithya”))
Agenda ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Introduction ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],Java Libraries JVM Evaluator Clojure/Repl Byte code public class  StringUtils  { public static boolean  isBlank (String str) { int strLen; if (str == null || (strLen = str.length()) == 0) { return true; } for (int i = 0; i < strLen; i++) { if ((Character.isWhitespace(str.charAt(i)) == false)) { return false; } } return true; } } ( defn  blank? [s]  ( every?  # ( Character/isWhitespace  % )  s ) ) Fn name parameters body
[object Object],[object Object],[object Object],[object Object],Features ,[object Object],[object Object],[object Object],[object Object],[object Object]
[object Object],[object Object],Features Ins to generate the next component seq Item First Rest ( defn  lazy-counter-iterate [base increment] (  iterate   ( fn  [n]  ( +  n increment ) )  base ) ) user=>  ( def  iterate-counter  ( lazy-counter-iterate  2   3 ) ) user=>  ( nth  iterate-counter  1000000 ) user=>  ( nth   ( lazy-counter-iterate  2   3 )   1000000 ) 3000002
[object Object],[object Object],[object Object],[object Object],State – You are doing it wrong Object Data Behaviour Object 2 Data Behaviour
Mutable  Variables ,[object Object],location:Chennai location:Bangalore Values  are constants, they never  change (def location (ref “”) ) Identity  - have different states in different point of time States  value of an identity
[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],Concurrency
[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],public   class   LinkedBlockingQueue <E>  public   E peek() { final   ReentrantLock takeLock =  this .takeLock; takeLock.lock(); try   { Node<E> first =  head . next ; if   (first ==  null ) return   null ; else return   first. item ; }  finally  { takeLock.unlock(); } } Locks
[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],C ompare  A nd  S wap
Enhancing Read Parallelism ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],public   boolean  add(E e) { final  ReentrantLock lock =  this . lock ; lock.lock(); try  {   Object[] elements = getArray();   int  len = elements. length ;   Object[] newElements = Arrays. copyOf (elements,  len + 1);   newElements[len] = e;   setArray(newElements);   return   true ; }  finally  {   lock.unlock(); }  }
[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],S oftware  T ransaction  M emory
Clojure  Transactions Txn Txn Adam Mr B Minion R ~ 40 U ~ 30 (defstruct stock :name :quantity) (struct stock “CSK” 40) StocksList R ~ 30 Buy 10 Buy 5 Sell 10 CSK ~ 30 Txn Fail & Retry R - 40 U ~ 35 R - 30 U - 25 U ~ 40 Transaction Creation -  (dosync  (...))
Clojure STM ,[object Object],[object Object],[object Object],[object Object],[object Object]
STM ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Persistent Data Structures ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
PersistentHashMap ,[object Object],static interface  INode { INode  assoc (int shift, int hash,  Object key, Object val, Box addedLeaf); LeafNode  find (int hash, Object key); } BitMapIndexedNode
Concurrency Library ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],Uncoordinated Coordinated Synchronous Var Atom Ref Asynchronous Agent
Vars ,[object Object],[object Object],[object Object],[object Object],[object Object],T1 T2 (def x 10)  ; Global object (defn get-val [] (+ x y)) (defn fn []  (println x) (binding [x 2] (get-val)) Can’t see the binded value
Vars ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],user=>  ( def  variable  1 ) #'user/variable user=>  ( . start  ( Thread.  ( fn  []  ( println  variable ) ) ) ) nil user=>  1 user=> (def variable 1) #'user/variable user=>(defn print [] (println variable)) user=> (.start (Thread. (fn [] (binding [variable 42] (print))))) nil user=> 1 (set! var-symbol value) (defn say-hello [] (println &quot;Hello&quot;))  (binding [say-hello #(println &quot;Goodbye&quot;)]  (say-hello))
Vars... ,[object Object],[object Object],[object Object],[object Object],[object Object],( ns  test-memoization ) ( defn  triple[n] ( Thread/sleep  100 ) ( *  n  3 ) ) ( defn  invoke_triple []   (  map  triple [  1   2   3   4   4   3   2   1 ] ) ) ( time   ( dorun   ( invoke_triple ) ) )   ->   &quot;Elapsed time: 801.084578 msecs&quot; ;(time (dorun (binding [triple (memoize triple)]  (invoke_triple)))) -> &quot;Elapsed time: 401.87119 msecs&quot;
Atoms ,[object Object],[object Object],[object Object],[object Object],(def current-track (atom “Ooh la la la”)) (deref current-track )  or  @current-track (reset! current-track “Humma Humma” (reset! current-track {:title : “Humma Humma”, composer” “What???”}) (def current-track (atom {:title : “Ooh la la la”, :composer: “ARR”})) (swap! current-track assoc {:title” : “Hosana”})
Refs ,[object Object],[object Object],[object Object],[object Object],[object Object]
Refs in Txn ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Changing Ref ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],( def  account1  ( ref   1000 ) ) ( def  account2  ( ref   2000 ) ) ( defn  transfer &quot;transfers amount of money from a to b&quot; [a b amount] ( dosync (  alter  a  -  amount ) (  alter  b  +  amount ) ) ) ( transfer account1 account2  300 ) ( transfer account2 account1  50 ) ;@account1  -> 750 ;@account2  -> 2250
Validators ,[object Object],[object Object],[object Object],(  ref  initial-value  :validator  validator-fn ) user=>  ( def  my-ref  ( ref   5 ) ) #'user/my-ref user=>  ( set-validator!  my-ref  ( fn  [x]  ( <   0  x ) ) ) Nil user=>  ( dosync   ( alter  my-ref –   10 ) ) #<CompilerException  java.lang.IllegalStateException:  Invalid Reference State> user=>  ( dosync   ( alter  my-ref –   10 )   ( alter  my-ref  +   15 ) ) 10 user=> @my-ref 5
Watches ,[object Object],[object Object],[object Object],(  add-watch   identity   key   watch-function ) ( defn  function-name [ key   identity  old-val  new-val] expressions ) ( remove-watch   identity   key ) user=>  ( defn  my-watch [ key   identity  old-val new-val] (  println   ( str   &quot;Old: &quot;  old-val ) ) (  println   ( str   &quot;New: &quot;  new-val ) ) ) #'user/my-watch user=>  ( def  my-ref  ( ref   5 ) ) #'user/my-ref user=>  ( add-watch  my-ref  &quot;watch1&quot;  my-watch ) #<Ref  5 > user=>  ( dosync   ( alter  my-ref  inc ) ) Old:  5
Other features... ,[object Object],[object Object],[object Object],[object Object],[object Object]
Agents ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Agents ,[object Object],[object Object],[object Object]
Agents ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Concurrency
Parallel Programming (defn heavy [f]  (fn [& args]  (Thread/sleep 1000) (apply f args))) (time (+ 5 5)) ;>>> &quot;Elapsed time: 0.035009 msecs&quot; (time ((heavy +) 5 5)) ;>>> &quot;Elapsed time: 1000.691607 msecs&quot; pmap (time (doall (map (heavy inc) [1 2 3 4 5]))) ;>>> &quot;Elapsed time: 5001.055055 msecs&quot; (time (doall (pmap (heavy inc) [1 2 3 4 5]))) ;>>> &quot;Elapsed time: 1004.219896 msecs&quot; ( pvalues  (+ 5 5) (- 5 3) (* 2 4)) ( pcalls  #(+ 5 2) #(* 2 5))
[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],Erlang Immutable Message Machine Machine Process Actors  - a process that executes a function.  Process  - a lightweight user-space thread. Mailbox  - essentially a queue with multiple producers
Actor Model ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Actor Model ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
References ,[object Object],[object Object],[object Object]

Más contenido relacionado

La actualidad más candente

Java 5 concurrency
Java 5 concurrencyJava 5 concurrency
Java 5 concurrency
priyank09
 
Other Approaches (Concurrency)
Other Approaches (Concurrency)Other Approaches (Concurrency)
Other Approaches (Concurrency)
Sri Prasanna
 
Николай Папирный Тема: "Java memory model для простых смертных"
Николай Папирный Тема: "Java memory model для простых смертных"Николай Папирный Тема: "Java memory model для простых смертных"
Николай Папирный Тема: "Java memory model для простых смертных"
Ciklum Minsk
 
Java 5 6 Generics, Concurrency, Garbage Collection, Tuning
Java 5 6 Generics, Concurrency, Garbage Collection, TuningJava 5 6 Generics, Concurrency, Garbage Collection, Tuning
Java 5 6 Generics, Concurrency, Garbage Collection, Tuning
Carol McDonald
 

La actualidad más candente (20)

Java Concurrency
Java ConcurrencyJava Concurrency
Java Concurrency
 
Java 5 concurrency
Java 5 concurrencyJava 5 concurrency
Java 5 concurrency
 
Byte code field report
Byte code field reportByte code field report
Byte code field report
 
Other Approaches (Concurrency)
Other Approaches (Concurrency)Other Approaches (Concurrency)
Other Approaches (Concurrency)
 
C++11 Multithreading - Futures
C++11 Multithreading - FuturesC++11 Multithreading - Futures
C++11 Multithreading - Futures
 
Николай Папирный Тема: "Java memory model для простых смертных"
Николай Папирный Тема: "Java memory model для простых смертных"Николай Папирный Тема: "Java memory model для простых смертных"
Николай Папирный Тема: "Java memory model для простых смертных"
 
Objective-C Blocks and Grand Central Dispatch
Objective-C Blocks and Grand Central DispatchObjective-C Blocks and Grand Central Dispatch
Objective-C Blocks and Grand Central Dispatch
 
Basics of Java Concurrency
Basics of Java ConcurrencyBasics of Java Concurrency
Basics of Java Concurrency
 
Java 10, Java 11 and beyond
Java 10, Java 11 and beyondJava 10, Java 11 and beyond
Java 10, Java 11 and beyond
 
Deuce STM - CMP'09
Deuce STM - CMP'09Deuce STM - CMP'09
Deuce STM - CMP'09
 
How and why I turned my old Java projects into a first-class serverless compo...
How and why I turned my old Java projects into a first-class serverless compo...How and why I turned my old Java projects into a first-class serverless compo...
How and why I turned my old Java projects into a first-class serverless compo...
 
An introduction to Rust: the modern programming language to develop safe and ...
An introduction to Rust: the modern programming language to develop safe and ...An introduction to Rust: the modern programming language to develop safe and ...
An introduction to Rust: the modern programming language to develop safe and ...
 
C++11 - STL Additions
C++11 - STL AdditionsC++11 - STL Additions
C++11 - STL Additions
 
Java 5 6 Generics, Concurrency, Garbage Collection, Tuning
Java 5 6 Generics, Concurrency, Garbage Collection, TuningJava 5 6 Generics, Concurrency, Garbage Collection, Tuning
Java 5 6 Generics, Concurrency, Garbage Collection, Tuning
 
Java memory model
Java memory modelJava memory model
Java memory model
 
Blocks & GCD
Blocks & GCDBlocks & GCD
Blocks & GCD
 
Modern Java Workshop
Modern Java WorkshopModern Java Workshop
Modern Java Workshop
 
Making Java more dynamic: runtime code generation for the JVM
Making Java more dynamic: runtime code generation for the JVMMaking Java more dynamic: runtime code generation for the JVM
Making Java more dynamic: runtime code generation for the JVM
 
Java collections the force awakens
Java collections  the force awakensJava collections  the force awakens
Java collections the force awakens
 
Wait for your fortune without Blocking!
Wait for your fortune without Blocking!Wait for your fortune without Blocking!
Wait for your fortune without Blocking!
 

Similar a Clojure concurrency

Os Reindersfinal
Os ReindersfinalOs Reindersfinal
Os Reindersfinal
oscon2007
 
Os Reindersfinal
Os ReindersfinalOs Reindersfinal
Os Reindersfinal
oscon2007
 
Software Transactioneel Geheugen
Software Transactioneel GeheugenSoftware Transactioneel Geheugen
Software Transactioneel Geheugen
Devnology
 
If You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are WrongIf You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are Wrong
Mario Fusco
 
FP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyondFP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyond
Mario Fusco
 
Concurrency on the JVM
Concurrency on the JVMConcurrency on the JVM
Concurrency on the JVM
Vaclav Pech
 

Similar a Clojure concurrency (20)

Server side JavaScript: going all the way
Server side JavaScript: going all the wayServer side JavaScript: going all the way
Server side JavaScript: going all the way
 
Clojure 1.1 And Beyond
Clojure 1.1 And BeyondClojure 1.1 And Beyond
Clojure 1.1 And Beyond
 
A Survey of Concurrency Constructs
A Survey of Concurrency ConstructsA Survey of Concurrency Constructs
A Survey of Concurrency Constructs
 
Concurrency Constructs Overview
Concurrency Constructs OverviewConcurrency Constructs Overview
Concurrency Constructs Overview
 
Os Reindersfinal
Os ReindersfinalOs Reindersfinal
Os Reindersfinal
 
Os Reindersfinal
Os ReindersfinalOs Reindersfinal
Os Reindersfinal
 
Software Transactioneel Geheugen
Software Transactioneel GeheugenSoftware Transactioneel Geheugen
Software Transactioneel Geheugen
 
JS everywhere 2011
JS everywhere 2011JS everywhere 2011
JS everywhere 2011
 
Pune Clojure Course Outline
Pune Clojure Course OutlinePune Clojure Course Outline
Pune Clojure Course Outline
 
Clojure: Practical functional approach on JVM
Clojure: Practical functional approach on JVMClojure: Practical functional approach on JVM
Clojure: Practical functional approach on JVM
 
The Road To Reactive with RxJava JEEConf 2016
The Road To Reactive with RxJava JEEConf 2016The Road To Reactive with RxJava JEEConf 2016
The Road To Reactive with RxJava JEEConf 2016
 
bluespec talk
bluespec talkbluespec talk
bluespec talk
 
Getting started with Clojure
Getting started with ClojureGetting started with Clojure
Getting started with Clojure
 
Get into Functional Programming with Clojure
Get into Functional Programming with ClojureGet into Functional Programming with Clojure
Get into Functional Programming with Clojure
 
Clojure concurrency overview
Clojure concurrency overviewClojure concurrency overview
Clojure concurrency overview
 
Introduction to clojure
Introduction to clojureIntroduction to clojure
Introduction to clojure
 
If You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are WrongIf You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are Wrong
 
FP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyondFP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyond
 
Principles of the Play framework
Principles of the Play frameworkPrinciples of the Play framework
Principles of the Play framework
 
Concurrency on the JVM
Concurrency on the JVMConcurrency on the JVM
Concurrency on the JVM
 

Último

EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
Earley Information Science
 

Último (20)

EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 

Clojure concurrency

  • 1. (do “Concurrency in Clojure”) (by (and “Alex” “Nithya”))
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13. Clojure Transactions Txn Txn Adam Mr B Minion R ~ 40 U ~ 30 (defstruct stock :name :quantity) (struct stock “CSK” 40) StocksList R ~ 30 Buy 10 Buy 5 Sell 10 CSK ~ 30 Txn Fail & Retry R - 40 U ~ 35 R - 30 U - 25 U ~ 40 Transaction Creation - (dosync (...))
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 33. Parallel Programming (defn heavy [f] (fn [& args] (Thread/sleep 1000) (apply f args))) (time (+ 5 5)) ;>>> &quot;Elapsed time: 0.035009 msecs&quot; (time ((heavy +) 5 5)) ;>>> &quot;Elapsed time: 1000.691607 msecs&quot; pmap (time (doall (map (heavy inc) [1 2 3 4 5]))) ;>>> &quot;Elapsed time: 5001.055055 msecs&quot; (time (doall (pmap (heavy inc) [1 2 3 4 5]))) ;>>> &quot;Elapsed time: 1004.219896 msecs&quot; ( pvalues (+ 5 5) (- 5 3) (* 2 4)) ( pcalls #(+ 5 2) #(* 2 5))
  • 34.
  • 35.
  • 36.
  • 37.

Notas del editor

  1. homoiconicity is a property of some programming languages, in which the primary representation of programs is also a data structure in a primitive type of the language itself, from the Greek words homo meaning the same and icon meaning representation. This makes metaprogramming easier than in a language without this property Each file generates a loader class of the same name with &amp;quot;__init&amp;quot; appended.